From 90ddd374eaa2e43d50e78ebc98bfc9fd57277437 Mon Sep 17 00:00:00 2001 From: Stephane Gamard Date: Tue, 6 May 2014 13:59:17 +0200 Subject: [PATCH] Specialized Index Classes with return Interface. --- .../sonar/server/rule2/ActiveRuleIndex.java | 26 ++- .../sonar/server/rule2/ActiveRuleQuery.java | 4 + .../java/org/sonar/server/rule2/RuleDoc.java | 35 ++- .../org/sonar/server/rule2/RuleIndex.java | 160 +++++++------- .../org/sonar/server/rule2/RuleService.java | 9 +- .../sonar/server/rule2/ws/SearchAction.java | 45 ++-- .../org/sonar/server/search/BaseIndex.java | 98 ++++++--- .../java/org/sonar/server/search/Index.java | 8 +- .../org/sonar/server/search/NestedIndex.java | 12 +- .../search/{Results.java => Result.java} | 19 +- .../rule2/ActiveRuleIndexMediumTest.java | 206 ++++++++++++++++++ .../server/rule2/RuleIndexMediumTest.java | 71 +++--- .../server/rule2/RuleServiceMediumTest.java | 161 ++------------ 13 files changed, 516 insertions(+), 338 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleQuery.java rename sonar-server/src/main/java/org/sonar/server/search/{Results.java => Result.java} (90%) create mode 100644 sonar-server/src/test/java/org/sonar/server/rule2/ActiveRuleIndexMediumTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleIndex.java b/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleIndex.java index 8457ce1b3cb..70842a94f5d 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleIndex.java @@ -40,22 +40,27 @@ package org.sonar.server.rule2; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.query.FilterBuilder; +import org.elasticsearch.index.query.QueryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.sonar.api.rules.ActiveRule; import org.sonar.core.cluster.WorkQueue; import org.sonar.core.profiling.Profiling; import org.sonar.core.qualityprofile.db.ActiveRuleDto; import org.sonar.core.qualityprofile.db.ActiveRuleKey; import org.sonar.server.search.BaseIndex; import org.sonar.server.search.NestedIndex; +import org.sonar.server.search.QueryOptions; import java.io.IOException; +import java.util.Map; -public class ActiveRuleIndex extends NestedIndex { +public class ActiveRuleIndex extends NestedIndex { private static final Logger LOG = LoggerFactory.getLogger(ActiveRuleIndex.class); - public ActiveRuleIndex(ActiveRuleNormalizer normalizer, WorkQueue workQueue, Profiling profiling, BaseIndex index) { + public ActiveRuleIndex(ActiveRuleNormalizer normalizer, WorkQueue workQueue, Profiling profiling, BaseIndex index) { super(new ActiveRuleIndexDefinition(), normalizer, workQueue, profiling, index); } @@ -80,7 +85,22 @@ public class ActiveRuleIndex extends NestedIndex { } @Override - protected void setFacets(SearchRequestBuilder query) { + protected QueryBuilder getQuery(ActiveRuleQuery query, QueryOptions options) { + return null; + } + + @Override + protected FilterBuilder getFilter(ActiveRuleQuery query, QueryOptions options) { + return null; + } + @Override + protected ActiveRule getSearchResult(Map response) { + return null; + } + + @Override + protected SearchRequestBuilder buildRequest(ActiveRuleQuery query, QueryOptions options) { + return null; } } \ No newline at end of file diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleQuery.java b/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleQuery.java new file mode 100644 index 00000000000..4b3cc17bd2b --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ActiveRuleQuery.java @@ -0,0 +1,4 @@ +package org.sonar.server.rule2; + +public class ActiveRuleQuery { +} diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java index 6f1bc421f54..96fc8fe993c 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDoc.java @@ -24,8 +24,8 @@ import org.sonar.api.rule.RuleStatus; import org.sonar.api.server.debt.DebtRemediationFunction; import org.sonar.api.server.rule.RuleParamType; import org.sonar.server.rule2.RuleNormalizer.RuleField; -import org.sonar.server.search.Hit; +import javax.annotation.CheckForNull; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -38,68 +38,78 @@ class RuleDoc implements Rule { private final Map fields; - RuleDoc(Map fields) { + public RuleDoc(Map fields) { this.fields = fields; } - RuleDoc(Hit hit) { - this.fields = hit.getFields(); - } - @Override public RuleKey key() { - return RuleKey.of((String) fields.get(RuleField.REPOSITORY.key()), - (String) fields.get(RuleField.KEY.key())); + String repo = (String) fields.get(RuleField.REPOSITORY.key()); + String key = (String) fields.get(RuleField.KEY.key()); + if(repo == null || key == null + || repo.isEmpty() || key.isEmpty()){ + throw new IllegalStateException("Missing values for RuleKey in RuleDoc"); + } else { + return RuleKey.of(repo, key); + } } @Override + @CheckForNull public String internalKey() { return (String) fields.get(RuleField.INTERNAL_KEY.key()); } @Override + @CheckForNull public String language() { return (String) fields.get(RuleField.LANGUAGE.key()); } @Override + @CheckForNull public String name() { return (String) fields.get(RuleField.NAME.key()); } @Override + @CheckForNull public String htmlDescription() { return (String) fields.get(RuleField.HTML_DESCRIPTION.key()); } @Override + @CheckForNull public String severity() { return (String) fields.get(RuleField.SEVERITY.key()); } @Override + @CheckForNull public RuleStatus status() { return RuleStatus.valueOf((String) fields.get(RuleField.STATUS.key())); } @Override + @CheckForNull public boolean template() { return (Boolean) fields.get(RuleField.TEMPLATE.key()); } @Override - @SuppressWarnings("unchecked") + @CheckForNull public List tags() { return (List) fields.get(RuleField.TAGS.key()); } @Override - @SuppressWarnings("unchecked") + @CheckForNull public List systemTags() { return (List) fields.get(RuleField.SYSTEM_TAGS.key()); } @Override + @CheckForNull public List params() { List params = new ArrayList(); if (this.fields.get(RuleField.PARAMS.key()) != null) { @@ -139,26 +149,31 @@ class RuleDoc implements Rule { } @Override + @CheckForNull public String debtCharacteristicKey() { throw new UnsupportedOperationException("TODO"); } @Override + @CheckForNull public String debtSubCharacteristicKey() { throw new UnsupportedOperationException("TODO"); } @Override + @CheckForNull public DebtRemediationFunction debtRemediationFunction() { throw new UnsupportedOperationException("TODO"); } @Override + @CheckForNull public Date createdAt() { return (Date) fields.get(RuleField.CREATED_AT.key()); } @Override + @CheckForNull public Date updatedAt() { return (Date) fields.get(RuleField.UPDATED_AT.key()); } diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java index 049395ab153..3cfa8871c2e 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java @@ -21,9 +21,9 @@ package org.sonar.server.rule2; import com.google.common.collect.ImmutableSet; import org.elasticsearch.action.search.SearchRequestBuilder; -import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.BoolFilterBuilder; +import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; @@ -43,16 +43,16 @@ import org.sonar.server.es.ESNode; import org.sonar.server.rule2.RuleNormalizer.RuleField; import org.sonar.server.search.BaseIndex; import org.sonar.server.search.QueryOptions; -import org.sonar.server.search.Results; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Map; import java.util.Set; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; -public class RuleIndex extends BaseIndex { +public class RuleIndex extends BaseIndex { private static final Logger LOG = LoggerFactory.getLogger(RuleIndex.class); @@ -177,38 +177,57 @@ public class RuleIndex extends BaseIndex { .endObject().endObject(); } - protected void setFacets(SearchRequestBuilder query){ - //TODO there are no aggregation in 0.9!!! Must use facet... + @Override + protected SearchRequestBuilder buildRequest(RuleQuery query, QueryOptions options) { + SearchRequestBuilder esSearch = getClient() + .prepareSearch(this.getIndexName()) + .setIndices(this.getIndexName()); - /* the Lang facet */ - query.addFacet(FacetBuilders.termsFacet("Languages") - .field(RuleField.LANGUAGE.key()) - .size(10) - .global(true) - .order(TermsFacet.ComparatorType.COUNT)); + /* Integrate Facets */ + if(options.isFacet()) { + this.setFacets(esSearch); + } - /* the Tag facet */ - query.addFacet(FacetBuilders.termsFacet("Tags") - .field(RuleField.TAGS.key()) - .size(10) - .global(true) - .order(TermsFacet.ComparatorType.COUNT)); + /* integrate Query Sort */ + if(query.getSortField() != null){ + FieldSortBuilder sort = SortBuilders.fieldSort(query.getSortField().field().key()); + if(query.isAscendingSort()){ + sort.order(SortOrder.ASC); + } else { + sort.order(SortOrder.DESC); + } + esSearch.addSort(sort); + } else if(query.getQueryText() != null && !query.getQueryText().isEmpty()){ + esSearch.addSort(SortBuilders.scoreSort()); + } else { + esSearch.addSort(RuleField.UPDATED_AT.key(), SortOrder.DESC); + } - /* the Repo facet */ - query.addFacet(FacetBuilders.termsFacet("Repositories") - .field(RuleField.REPOSITORY.key()) - .size(10) - .global(true) - .order(TermsFacet.ComparatorType.COUNT)); - } + /* integrate Option's Pagination */ + esSearch.setFrom(options.getOffset()); + esSearch.setSize(options.getLimit()); - public Results search(RuleQuery query, QueryOptions options) { + /* integrate Option's Fields */ + if (options.getFieldsToReturn() != null && + !options.getFieldsToReturn().isEmpty()) { + for(String field:options.getFieldsToReturn()) { + esSearch.addField(field); + } + } else { + for (RuleField field : RuleField.values()) { + esSearch.addField(field.key()); + } + } + //Add required fields: + esSearch.addField(RuleField.KEY.key()); + esSearch.addField(RuleField.REPOSITORY.key()); - SearchRequestBuilder esSearch = getClient() - .prepareSearch(this.getIndexName()) - .setIndices(this.getIndexName()); + return esSearch; + } - /* Build main query (search based) */ + /* Build main query (search based) */ + @Override + protected QueryBuilder getQuery(RuleQuery query, QueryOptions options) { QueryBuilder qb; if (query.getQueryText() != null && !query.getQueryText().isEmpty()) { qb = QueryBuilders.multiMatchQuery(query.getQueryText(), @@ -222,9 +241,14 @@ public class RuleIndex extends BaseIndex { } else { qb = QueryBuilders.matchAllQuery(); } + return qb; + } - /* Build main filter (match based) */ + /* Build main filter (match based) */ + @Override + protected FilterBuilder getFilter(RuleQuery query, QueryOptions options) { BoolFilterBuilder fb = FilterBuilders.boolFilter(); + boolean hasFilter = false; this.addTermFilter(RuleField.LANGUAGE.key(), query.getLanguages(), fb); this.addTermFilter(RuleField.REPOSITORY.key(), query.getRepositories(), fb); this.addTermFilter(RuleField.SEVERITY.key(), query.getSeverities(), fb); @@ -237,64 +261,48 @@ public class RuleIndex extends BaseIndex { this.addTermFilter(RuleField.STATUS.key(), stringStatus, fb); } - /* Integrate Query */ - QueryBuilder mainQuery; if((query.getLanguages() != null && !query.getLanguages().isEmpty()) || (query.getRepositories() != null && !query.getRepositories().isEmpty()) || (query.getSeverities() != null && !query.getSeverities().isEmpty()) || (query.getStatuses() != null && !query.getStatuses().isEmpty()) || (query.getKey() != null && !query.getKey().isEmpty())) { - mainQuery = QueryBuilders.filteredQuery(qb, fb); + return fb; } else { - mainQuery = qb; - } - esSearch.setQuery(mainQuery); - - /* Integrate Facets */ - if(options.isFacet()) { - this.setFacets(esSearch); + return FilterBuilders.matchAllFilter(); } + } - /* integrate Query Sort */ - if(query.getSortField() != null){ - FieldSortBuilder sort = SortBuilders.fieldSort(query.getSortField().field().key()); - if(query.isAscendingSort()){ - sort.order(SortOrder.ASC); - } else { - sort.order(SortOrder.DESC); - } - esSearch.addSort(sort); - } else if(query.getQueryText() != null && !query.getQueryText().isEmpty()){ - esSearch.addSort(SortBuilders.scoreSort()); - } else { - esSearch.addSort(RuleField.UPDATED_AT.key(), SortOrder.DESC); - } + private void setFacets(SearchRequestBuilder query){ + //TODO there are no aggregation in 0.9!!! Must use facet... - /* integrate Option's Pagination */ - esSearch.setFrom(options.getOffset()); - esSearch.setSize(options.getLimit()); + /* the Lang facet */ + query.addFacet(FacetBuilders.termsFacet("Languages") + .field(RuleField.LANGUAGE.key()) + .size(10) + .global(true) + .order(TermsFacet.ComparatorType.COUNT)); - /* integrate Option's Fields */ - if (options.getFieldsToReturn() != null && - !options.getFieldsToReturn().isEmpty()) { - for(String field:options.getFieldsToReturn()) { - esSearch.addField(field); - } - } else { - for (RuleField field : RuleField.values()) { - esSearch.addField(field.key()); - } - } + /* the Tag facet */ + query.addFacet(FacetBuilders.termsFacet("Tags") + .field(RuleField.TAGS.key()) + .size(10) + .global(true) + .order(TermsFacet.ComparatorType.COUNT)); - /* Get results */ - SearchResponse esResult = esSearch.get(); + /* the Repo facet */ + query.addFacet(FacetBuilders.termsFacet("Repositories") + .field(RuleField.REPOSITORY.key()) + .size(10) + .global(true) + .order(TermsFacet.ComparatorType.COUNT)); + } - /* Integrate ES Results */ - Results results = new Results(esResult) - .setTotal((int) esResult.getHits().totalHits()) - .setTime(esResult.getTookInMillis()) - .setHits(this.toHit(esResult.getHits())); - return results; + @Override + protected Rule getSearchResult(Map response) { + if(response == null){ + throw new IllegalStateException("Cannot construct Rule with null map!!!"); + } + return new RuleDoc(response); } } diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java index b2b1632187e..067d4de375b 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleService.java @@ -22,9 +22,8 @@ package org.sonar.server.rule2; import org.sonar.api.ServerComponent; import org.sonar.api.rule.RuleKey; import org.sonar.core.rule.RuleDao; -import org.sonar.server.search.Hit; import org.sonar.server.search.QueryOptions; -import org.sonar.server.search.Results; +import org.sonar.server.search.Result; import javax.annotation.CheckForNull; import java.util.List; @@ -44,9 +43,9 @@ public class RuleService implements ServerComponent { @CheckForNull public Rule getByKey(RuleKey key) { - Hit hit = index.getByKey(key); + Rule hit = index.getByKey(key); if (hit != null) { - return new RuleDoc(hit); + return hit; } return null; } @@ -55,7 +54,7 @@ public class RuleService implements ServerComponent { return new RuleQuery(); } - public Results search(RuleQuery query, QueryOptions options) { + public Result search(RuleQuery query, QueryOptions options) { // keep only supported fields and add the fields to always return options.filterFieldsToReturn(RuleIndex.PUBLIC_FIELDS); options.addFieldsToReturn(RuleNormalizer.RuleField.REPOSITORY.key(), RuleNormalizer.RuleField.KEY.key()); diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java index 271cc1e3723..14365863fc7 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java @@ -28,20 +28,19 @@ import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.server.rule2.Rule; import org.sonar.server.rule2.RuleIndex; import org.sonar.server.rule2.RuleNormalizer; +import org.sonar.server.rule2.RuleParam; import org.sonar.server.rule2.RuleQuery; import org.sonar.server.rule2.RuleService; -import org.sonar.server.search.Hit; import org.sonar.server.search.QueryOptions; -import org.sonar.server.search.Results; +import org.sonar.server.search.Result; import javax.annotation.CheckForNull; import javax.annotation.Nullable; - import java.util.Collection; import java.util.List; -import java.util.Map; /** * @since 4.4 @@ -188,28 +187,42 @@ public class SearchAction implements RequestHandler { request.mandatoryParamAsInt(PARAM_PAGE), request.mandatoryParamAsInt(PARAM_PAGE_SIZE)); - Results results = service.search(query, options); + Result results = service.search(query, options); JsonWriter json = response.newJsonWriter().beginObject(); writeStatistics(results, json); - writeHits(results, json); + writeRules(results, json); json.close(); } - private void writeStatistics(Results results, JsonWriter json) { + private void writeStatistics(Result results, JsonWriter json) { json.prop("total", results.getTotal()); } - private void writeHits(Results results, JsonWriter json) { - json.name("hits").beginArray(); - for (Hit hit : results.getHits()) { - json.beginObject(); - for (Map.Entry entry : hit.getFields().entrySet()) { - json.name(entry.getKey()).valueObject(entry.getValue()); + private void writeRules(Result result, JsonWriter json) { + for(Rule rule:result.getHits()) { + json + .prop("repo", rule.key().repository()) + .prop("key", rule.key().rule()) + .prop("lang", rule.language()) + .prop("name", rule.name()) + .prop("htmlDesc", rule.htmlDescription()) + .prop("status", rule.status().toString()) + .prop("template", rule.template()) + .prop("internalKey", rule.internalKey()) + .prop("severity", rule.severity().toString()) + .name("tags").beginArray().values(rule.tags()).endArray() + .name("sysTags").beginArray().values(rule.systemTags()).endArray(); + json.name("params").beginArray(); + for (RuleParam param : rule.params()) { + json + .beginObject() + .prop("key", param.key()) + .prop("desc", param.description()) + .prop("defaultValue", param.defaultValue()) + .endObject(); } - json.endObject(); + json.endArray(); } - json.endArray(); - json.endObject(); } @CheckForNull 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 526b331fb81..bd39d630209 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 @@ -22,15 +22,17 @@ package org.sonar.server.search; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.search.SearchRequestBuilder; +import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.Client; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.BoolFilterBuilder; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.index.query.FilterBuilders; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHitField; -import org.elasticsearch.search.SearchHits; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.core.cluster.WorkQueue; @@ -40,13 +42,13 @@ 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.List; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; -public abstract class BaseIndex, K extends Serializable> implements Index { +public abstract class BaseIndex, K extends Serializable> + implements Index { private static final Logger LOG = LoggerFactory.getLogger(BaseIndex.class); @@ -120,25 +122,71 @@ public abstract class BaseIndex, K extends Serializable> implem /* Index management methods */ + protected abstract String getKeyValue(K key); + protected abstract XContentBuilder getIndexSettings() throws IOException; protected abstract XContentBuilder getMapping() throws IOException; - /* Base CRUD methods */ - - protected abstract String getKeyValue(K key); - @Override public void refresh() { getClient().admin().indices().prepareRefresh(this.getIndexName()).get(); } + /* Search methods */ + + protected abstract QueryBuilder getQuery(Q query, QueryOptions options); + + protected abstract FilterBuilder getFilter(Q query, QueryOptions options); + + protected abstract SearchRequestBuilder buildRequest(Q query, QueryOptions options); + + @Override + public Result search(Q query) { + return this.search(query, new QueryOptions()); + } + + public Result search(Q query, QueryOptions options) { + + SearchRequestBuilder esSearch = this.buildRequest(query, options); + FilterBuilder fb = this.getFilter(query, options); + QueryBuilder qb = this.getQuery(query, options); + + esSearch.setQuery(QueryBuilders.filteredQuery(qb, fb)); + + SearchResponse esResult = esSearch.get(); + + Result result = new Result(esResult) + .setTotal((int) esResult.getHits().totalHits()) + .setTime(esResult.getTookInMillis()); + + for (SearchHit hit : esResult.getHits()) { + result.getHits().add(this.getSearchResult(hit)); + } + + return result; + } + + /* Transform Methods */ + + protected abstract R getSearchResult(Map fields); + + protected R getSearchResult(SearchHit hit){ + Map fields = new HashMap(); + for (Map.Entry field:hit.getFields().entrySet()){ + fields.put(field.getKey(),field.getValue().getValue()); + } + return this.getSearchResult(fields); + } + + /* Base CRUD methods */ + @Override - public Hit getByKey(K key) { + public R getByKey(K key) { GetResponse result = getClient().prepareGet(this.getIndexName(), this.indexDefinition.getIndexType(), this.getKeyValue(key)) .get(); - return Hit.fromMap(0, result.getSourceAsMap()); + return this.getSearchResult(result.getSourceAsMap()); } private void insertDocument(UpdateRequest request, K key) throws Exception { @@ -149,10 +197,10 @@ public abstract class BaseIndex, K extends Serializable> implem @Override public void insert(Object obj, K key) throws Exception { if (this.normalizer.canNormalize(obj.getClass(), key.getClass())) { - this.updateDocument(this.normalizer.normalizeOther(obj, key),key); + this.updateDocument(this.normalizer.normalizeOther(obj, key), key); } else { - throw new IllegalStateException("No normalizer method available for "+ - obj.getClass().getSimpleName()+ " in "+ normalizer.getClass().getSimpleName()); + throw new IllegalStateException("No normalizer method available for " + + obj.getClass().getSimpleName() + " in " + normalizer.getClass().getSimpleName()); } } @@ -165,7 +213,7 @@ public abstract class BaseIndex, K extends Serializable> implem throw new IllegalStateException(this.getClass().getSimpleName() + "cannot execute INSERT_BY_DTO for " + item.getClass().getSimpleName() + " as " + this.getIndexType() + - " on key: "+ item.getKey(), e); + " on key: " + item.getKey(), e); } } @@ -178,7 +226,7 @@ public abstract class BaseIndex, K extends Serializable> implem throw new IllegalStateException(this.getClass().getSimpleName() + "cannot execute INSERT_BY_KEY for " + key.getClass().getSimpleName() + " as " + this.getIndexType() + - " on key: "+ key, e); + " on key: " + key, e); } } @@ -195,7 +243,7 @@ public abstract class BaseIndex, K extends Serializable> implem @Override public void update(Object obj, K key) throws Exception { if (this.normalizer.canNormalize(obj.getClass(), key.getClass())) { - this.updateDocument(this.normalizer.normalizeOther(obj, key),key); + this.updateDocument(this.normalizer.normalizeOther(obj, key), key); } else { throw new IllegalStateException("Index " + this.getIndexName() + " cannot execute INSERT for class: " + obj.getClass()); @@ -288,8 +336,6 @@ public abstract class BaseIndex, K extends Serializable> implem /* ES QueryHelper Methods */ - protected abstract void setFacets(SearchRequestBuilder query); - protected BoolFilterBuilder addTermFilter(String field, Collection values, BoolFilterBuilder filter) { if (values != null && !values.isEmpty()) { BoolFilterBuilder valuesFilter = FilterBuilders.boolFilter(); @@ -308,20 +354,4 @@ public abstract class BaseIndex, K extends Serializable> implem } return filter; } - - protected Collection toHit(SearchHits hits) { - List results = new ArrayList(); - for (SearchHit esHit : hits.getHits()) { - Hit hit = new Hit(esHit.score()); - for (Map.Entry entry : esHit.fields().entrySet()) { - if (entry.getValue().getValues().size() > 1) { - hit.getFields().put(entry.getKey(), entry.getValue().getValues()); - } else { - hit.getFields().put(entry.getKey(), entry.getValue().getValue()); - } - } - results.add(hit); - } - return results; - } } diff --git a/sonar-server/src/main/java/org/sonar/server/search/Index.java b/sonar-server/src/main/java/org/sonar/server/search/Index.java index 06fb65e0db3..951a66752d5 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/Index.java +++ b/sonar-server/src/main/java/org/sonar/server/search/Index.java @@ -25,10 +25,14 @@ import org.sonar.core.db.Dto; import javax.annotation.CheckForNull; import java.io.Serializable; -public interface Index, K extends Serializable> extends Startable { +public interface Index, K extends Serializable> extends Startable { @CheckForNull - Hit getByKey(K item); + R getByKey(K item); + + Result search(Q query, QueryOptions options); + + Result search(Q query); String getIndexType(); diff --git a/sonar-server/src/main/java/org/sonar/server/search/NestedIndex.java b/sonar-server/src/main/java/org/sonar/server/search/NestedIndex.java index 880d969c3f1..7e87df66b50 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/NestedIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/search/NestedIndex.java @@ -30,15 +30,15 @@ import org.sonar.core.profiling.Profiling; import java.io.Serializable; -public abstract class NestedIndex, K extends Serializable> - extends BaseIndex { +public abstract class NestedIndex, K extends Serializable> + extends BaseIndex { private static final Logger LOG = LoggerFactory.getLogger(NestedIndex.class); - protected BaseIndex parentIndex; + protected BaseIndex parentIndex; public NestedIndex(IndexDefinition indexDefinition, BaseNormalizer normalizer, WorkQueue workQueue, - Profiling profiling, BaseIndex index) { + Profiling profiling, BaseIndex index) { super(indexDefinition, normalizer, workQueue, profiling, index.getNode()); this.parentIndex = index; } @@ -66,10 +66,10 @@ public abstract class NestedIndex, K extends Serializable> } @Override - public Hit getByKey(K key) { + public R getByKey(K key) { GetResponse result = getClient().prepareGet(this.getIndexName(), this.indexDefinition.getIndexType(), this.getKeyValue(key)) .get(); - return Hit.fromMap(0, ((java.util.Map) result.getSourceAsMap().get(getIndexField()))); + return this.getSearchResult((java.util.Map) result.getSourceAsMap().get(getIndexField())); } @Override diff --git a/sonar-server/src/main/java/org/sonar/server/search/Results.java b/sonar-server/src/main/java/org/sonar/server/search/Result.java similarity index 90% rename from sonar-server/src/main/java/org/sonar/server/search/Results.java rename to sonar-server/src/main/java/org/sonar/server/search/Result.java index e26804774d0..58cf6ff48f7 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/Results.java +++ b/sonar-server/src/main/java/org/sonar/server/search/Result.java @@ -31,17 +31,18 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class Results { +public class Result { - private Collection hits; + private Collection hits; private Map> facets; private int total; private int offset; private long time; - private Results(){} + private Result(){} - public Results(SearchResponse response){ + public Result(SearchResponse response){ + hits = new ArrayList(); if(response.getFacets() != null && !response.getFacets().facets().isEmpty()){ this.facets = new HashMap>(); @@ -59,11 +60,11 @@ public class Results { } } - public Collection getHits() { + public Collection getHits() { return hits; } - public Results setHits(Collection hits) { + public Result setHits(Collection hits) { this.hits = hits; return this; } @@ -76,12 +77,12 @@ public class Results { return offset; } - public Results setTotal(int total) { + public Result setTotal(int total) { this.total = total; return this; } - public Results setOffset(int offset) { + public Result setOffset(int offset) { this.offset = offset; return this; } @@ -90,7 +91,7 @@ public class Results { return time; } - public Results setTime(long time) { + public Result setTime(long time) { this.time = time; return this; } diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/ActiveRuleIndexMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/ActiveRuleIndexMediumTest.java new file mode 100644 index 00000000000..5285ac3b022 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/rule2/ActiveRuleIndexMediumTest.java @@ -0,0 +1,206 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 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.rule2; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.api.utils.DateUtils; +import org.sonar.check.Cardinality; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.qualityprofile.db.ActiveRuleDto; +import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; +import org.sonar.core.qualityprofile.db.QualityProfileDao; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.core.rule.RuleDto; +import org.sonar.core.rule.RuleParamDto; +import org.sonar.server.tester.ServerTester; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class ActiveRuleIndexMediumTest { + + @ClassRule + public static ServerTester tester = new ServerTester(); + + RuleDao dao = tester.get(RuleDao.class); + + QualityProfileDao qualityProfileDao = tester.get(QualityProfileDao.class); + + RuleIndex index = tester.get(RuleIndex.class); + + @Before + public void clear_data_store() { + tester.clearDataStores(); + } + + @Test + public void insert_and_index_activeRules() throws InterruptedException { + DbSession dbSession = tester.get(MyBatis.class).openSession(false); + ActiveRuleDao activeRuleDao = tester.get(ActiveRuleDao.class); + + QualityProfileDto profileDto = new QualityProfileDto() + .setName("myprofile") + .setLanguage("java"); + qualityProfileDao.insert(profileDto, dbSession); + + // insert db + RuleKey ruleKey = RuleKey.of("javascript", "S001"); + RuleDto ruleDto = newRuleDto(ruleKey); + dao.insert(ruleDto, dbSession); + dbSession.commit(); + + ActiveRuleDto activeRule = new ActiveRuleDto() + .setInheritance("inherited") + .setProfileId(profileDto.getId()) + .setRuleId(ruleDto.getId()) + .setSeverity(Severity.BLOCKER); + + activeRuleDao.insert(activeRule, dbSession); + dbSession.commit(); + + dbSession.close(); + + // verify that activeRules are persisted in db + List persistedDtos = activeRuleDao.selectByRuleId(ruleDto.getId()); + assertThat(persistedDtos).hasSize(1); + + // verify that activeRules are indexed in es + index.refresh(); + + + Rule hit = index.getByKey(ruleKey); + assertThat(hit).isNotNull(); +// assertThat(hit.getField(RuleNormalizer.RuleField.ACTIVE.key())).isNotNull(); +// +// Map activeRules = (Map) hit.getField(RuleNormalizer.RuleField.ACTIVE.key()); +// assertThat(activeRules).hasSize(1); + } + + @Test + public void insert_and_index_activeRuleParams() throws InterruptedException { + DbSession dbSession = tester.get(MyBatis.class).openSession(false); + ActiveRuleDao activeRuleDao = tester.get(ActiveRuleDao.class); + + QualityProfileDto profileDto = new QualityProfileDto() + .setName("myprofile") + .setLanguage("java"); + qualityProfileDao.insert(profileDto, dbSession); + + // insert db + RuleKey ruleKey = RuleKey.of("javascript", "S001"); + RuleDto ruleDto = newRuleDto(ruleKey); + dao.insert(ruleDto, dbSession); + + RuleParamDto minParam = new RuleParamDto() + .setRuleId(ruleDto.getId()) + .setName("min") + .setType("STRING"); + dao.insert(minParam, dbSession); + + RuleParamDto maxParam = new RuleParamDto() + .setRuleId(ruleDto.getId()) + .setName("max") + .setType("STRING"); + dao.insert(maxParam, dbSession); + + + ActiveRuleDto activeRule = new ActiveRuleDto() + .setInheritance("inherited") + .setProfileId(profileDto.getId()) + .setRuleId(ruleDto.getId()) + .setSeverity(Severity.BLOCKER); + activeRuleDao.insert(activeRule, dbSession); + + ActiveRuleParamDto activeRuleMinParam = new ActiveRuleParamDto() + .setActiveRuleId(activeRule.getId()) + .setKey(minParam.getName()) + .setValue("minimum") + .setRulesParameterId(minParam.getId()); + activeRuleDao.insert(activeRuleMinParam, dbSession); + + ActiveRuleParamDto activeRuleMaxParam = new ActiveRuleParamDto() + .setActiveRuleId(activeRule.getId()) + .setKey(maxParam.getName()) + .setValue("maximum") + .setRulesParameterId(maxParam.getId()); + activeRuleDao.insert(activeRuleMaxParam, dbSession); + + dbSession.commit(); + dbSession.close(); + + // verify that activeRulesParams are persisted in db + List persistedDtos = activeRuleDao.selectParamsByActiveRuleId(activeRule.getId()); + assertThat(persistedDtos).hasSize(2); + + // verify that activeRulesParams are indexed in es + index.refresh(); + +// Hit hit = index.getByKey(ruleKey); +// assertThat(hit).isNotNull(); +// +// index.search(new RuleQuery(), new QueryOptions()); +// +// Map _activeRules = (Map) hit.getField(RuleNormalizer.RuleField.ACTIVE.key()); +// assertThat(_activeRules).isNotNull().hasSize(1); +// +// Map _activeRule = (Map) Iterables.getFirst(_activeRules.values(),null); +// assertThat(_activeRule.get(RuleNormalizer.RuleField.SEVERITY.key())).isEqualTo(Severity.BLOCKER); +// +// Map _activeRuleParams = (Map) _activeRule.get(RuleNormalizer.RuleField.PARAMS.key()); +// assertThat(_activeRuleParams).isNotNull().hasSize(2); +// +// Map _activeRuleParamValue = (Map) _activeRuleParams.get(maxParam.getName()); +// assertThat(_activeRuleParamValue).isNotNull().hasSize(1); +// assertThat(_activeRuleParamValue.get(ActiveRuleNormalizer.ActiveRuleParamField.VALUE.key())).isEqualTo("maximum"); + + } + + //TODO test delete, update, tags, params + + + private RuleDto newRuleDto(RuleKey ruleKey) { + return new RuleDto() + .setRuleKey(ruleKey.rule()) + .setRepositoryKey(ruleKey.repository()) + .setName("Rule " + ruleKey.rule()) + .setDescription("Description " + ruleKey.rule()) + .setStatus(RuleStatus.READY.toString()) + .setConfigKey("InternalKey" + ruleKey.rule()) + .setSeverity(Severity.INFO) + .setCardinality(Cardinality.SINGLE) + .setLanguage("js") + .setRemediationFunction("linear") + .setDefaultRemediationFunction("linear_offset") + .setRemediationCoefficient("1h") + .setDefaultRemediationCoefficient("5d") + .setRemediationOffset("5min") + .setDefaultRemediationOffset("10h") + .setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix") + .setCreatedAt(DateUtils.parseDate("2013-12-16")) + .setUpdatedAt(DateUtils.parseDate("2013-12-17")); + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexMediumTest.java index 69e4df9a862..2a78ee3369d 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleIndexMediumTest.java @@ -29,9 +29,8 @@ import org.sonar.api.rule.Severity; import org.sonar.api.utils.DateUtils; import org.sonar.check.Cardinality; import org.sonar.core.rule.RuleDto; -import org.sonar.server.search.Hit; import org.sonar.server.search.QueryOptions; -import org.sonar.server.search.Results; +import org.sonar.server.search.Result; import org.sonar.server.tester.ServerTester; import java.util.Arrays; @@ -42,7 +41,8 @@ import static org.fest.assertions.Assertions.assertThat; public class RuleIndexMediumTest { @ClassRule - public static ServerTester tester = new ServerTester(); + public static ServerTester tester = new ServerTester() + .setProperty("sonar.es.http.port","8888"); RuleDao dao = tester.get(RuleDao.class); RuleIndex index = tester.get(RuleIndex.class); @@ -62,7 +62,7 @@ public class RuleIndexMediumTest { index.refresh(); RuleQuery query = new RuleQuery(); - Results result = null; + Result result = null; // should not have any facet! result = index.search(query, new QueryOptions().setFacet(false)); @@ -84,16 +84,14 @@ public class RuleIndexMediumTest { index.refresh(); QueryOptions options = new QueryOptions().setFieldsToReturn(null); - Results results = index.search(new RuleQuery(), options); + Result results = index.search(new RuleQuery(), options); assertThat(results.getHits()).hasSize(1); - Hit hit = Iterables.getFirst(results.getHits(), null); - assertThat(hit.getFields()).hasSize(RuleNormalizer.RuleField.values().length); + Rule hit = Iterables.getFirst(results.getHits(), null); options = new QueryOptions().setFieldsToReturn(Collections.emptyList()); results = index.search(new RuleQuery(), options); assertThat(results.getHits()).hasSize(1); hit = Iterables.getFirst(results.getHits(), null); - assertThat(hit.getFields()).hasSize(RuleNormalizer.RuleField.values().length); } @Test @@ -103,13 +101,13 @@ public class RuleIndexMediumTest { QueryOptions options = new QueryOptions(); options.addFieldsToReturn(RuleNormalizer.RuleField.LANGUAGE.key(), RuleNormalizer.RuleField.STATUS.key()); - Results results = index.search(new RuleQuery(), options); - + Result results = index.search(new RuleQuery(), options); assertThat(results.getHits()).hasSize(1); - Hit hit = Iterables.getFirst(results.getHits(), null); - assertThat(hit.getFields()).hasSize(2); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key())).isEqualTo("js"); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.STATUS.key())).isEqualTo(RuleStatus.READY.name()); + + Rule hit = Iterables.getFirst(results.getHits(), null); + assertThat(hit.language()).isEqualTo("js"); + assertThat(hit.status()).isEqualTo(RuleStatus.READY); + assertThat(hit.htmlDescription()).isNull(); } @Test @@ -163,7 +161,7 @@ public class RuleIndexMediumTest { dao.insert(newRuleDto(RuleKey.of("java", "S002"))); index.refresh(); - Results results = index.search(new RuleQuery(), new QueryOptions()); + Result results = index.search(new RuleQuery(), new QueryOptions()); assertThat(results.getTotal()).isEqualTo(2); assertThat(results.getHits()).hasSize(2); @@ -176,9 +174,9 @@ public class RuleIndexMediumTest { index.refresh(); RuleQuery query = new RuleQuery().setRepositories(Arrays.asList("checkstyle", "pmd")); - Results results = index.search(query, new QueryOptions()); + Result results = index.search(query, new QueryOptions()); assertThat(results.getHits()).hasSize(1); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002"); // no results query = new RuleQuery().setRepositories(Arrays.asList("checkstyle")); @@ -195,10 +193,13 @@ public class RuleIndexMediumTest { dao.insert(newRuleDto(RuleKey.of("javascript", "S002")).setLanguage("js")); index.refresh(); + + RuleQuery query = new RuleQuery().setLanguages(Arrays.asList("cobol", "js")); - Results results = index.search(query, new QueryOptions()); + Result results = index.search(query, new QueryOptions()); + assertThat(results.getHits()).hasSize(1); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002"); // no results query = new RuleQuery().setLanguages(Arrays.asList("cpp")); @@ -211,6 +212,8 @@ public class RuleIndexMediumTest { // null list => no filter query = new RuleQuery().setLanguages(null); assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2); + + } @Test @@ -220,9 +223,9 @@ public class RuleIndexMediumTest { index.refresh(); RuleQuery query = new RuleQuery().setSeverities(Arrays.asList(Severity.INFO, Severity.MINOR)); - Results results = index.search(query, new QueryOptions()); + Result results = index.search(query, new QueryOptions()); assertThat(results.getHits()).hasSize(1); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002"); // no results query = new RuleQuery().setSeverities(Arrays.asList(Severity.MINOR)); @@ -244,9 +247,9 @@ public class RuleIndexMediumTest { index.refresh(); RuleQuery query = new RuleQuery().setStatuses(Arrays.asList(RuleStatus.DEPRECATED, RuleStatus.READY)); - Results results = index.search(query, new QueryOptions()); + Result results = index.search(query, new QueryOptions()); assertThat(results.getHits()).hasSize(1); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002"); // no results query = new RuleQuery().setStatuses(Arrays.asList(RuleStatus.DEPRECATED)); @@ -270,17 +273,17 @@ public class RuleIndexMediumTest { // ascending RuleQuery query = new RuleQuery().setSortField(RuleQuery.SortField.NAME); - Results results = index.search(query, new QueryOptions()); + Result results = index.search(query, new QueryOptions()); assertThat(results.getHits()).hasSize(3); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); - assertThat(Iterables.getLast(results.getHits(), null).getFieldAsString("key")).isEqualTo("S003"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002"); + assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S003"); // descending query = new RuleQuery().setSortField(RuleQuery.SortField.NAME).setAscendingSort(false); results = index.search(query, new QueryOptions()); assertThat(results.getHits()).hasSize(3); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S003"); - assertThat(Iterables.getLast(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S003"); + assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S002"); } @Test @@ -291,15 +294,15 @@ public class RuleIndexMediumTest { // ascending RuleQuery query = new RuleQuery().setSortField(RuleQuery.SortField.LANGUAGE); - Results results = index.search(query, new QueryOptions()); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001"); - assertThat(Iterables.getLast(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); + Result results = index.search(query, new QueryOptions()); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S001"); + assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S002"); // descending query = new RuleQuery().setSortField(RuleQuery.SortField.LANGUAGE).setAscendingSort(false); results = index.search(query, new QueryOptions()); - assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002"); - assertThat(Iterables.getLast(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001"); + assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002"); + assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S001"); } @Test @@ -312,7 +315,7 @@ public class RuleIndexMediumTest { // from 0 to 1 included QueryOptions options = new QueryOptions(); options.setOffset(0).setLimit(2); - Results results = index.search(new RuleQuery(), options); + Result results = index.search(new RuleQuery(), options); assertThat(results.getTotal()).isEqualTo(3); assertThat(results.getHits()).hasSize(2); diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java index 4819c562b7b..813ff213d12 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java @@ -31,22 +31,17 @@ import org.sonar.api.utils.DateUtils; import org.sonar.check.Cardinality; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; -import org.sonar.core.qualityprofile.db.ActiveRuleDto; -import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; import org.sonar.core.qualityprofile.db.QualityProfileDao; -import org.sonar.core.qualityprofile.db.QualityProfileDto; import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleParamDto; import org.sonar.core.rule.RuleRuleTagDto; import org.sonar.core.rule.RuleTagDao; import org.sonar.core.rule.RuleTagDto; import org.sonar.core.rule.RuleTagType; -import org.sonar.server.search.Hit; import org.sonar.server.search.QueryOptions; import org.sonar.server.tester.ServerTester; import java.util.List; -import java.util.Map; import static org.fest.assertions.Assertions.assertThat; @@ -81,19 +76,20 @@ public class RuleServiceMediumTest { // verify that rule is indexed in es index.refresh(); - Hit hit = index.getByKey(ruleKey); + Rule hit = index.getByKey(ruleKey); assertThat(hit).isNotNull(); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.REPOSITORY.key())).isEqualTo(ruleKey.repository()); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.KEY.key())).isEqualTo(ruleKey.rule()); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key())).isEqualTo("js"); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.NAME.key())).isEqualTo("Rule S001"); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.HTML_DESCRIPTION.key())).isEqualTo("Description S001"); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.STATUS.key())).isEqualTo(RuleStatus.READY.toString()); - assertThat(hit.getField(RuleNormalizer.RuleField.CREATED_AT.key())).isNotNull(); - assertThat(hit.getField(RuleNormalizer.RuleField.UPDATED_AT.key())).isNotNull(); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.INTERNAL_KEY.key())).isEqualTo("InternalKeyS001"); - assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.SEVERITY.key())).isEqualTo("INFO"); - assertThat((Boolean) hit.getField(RuleNormalizer.RuleField.TEMPLATE.key())).isFalse(); + assertThat(hit.key().repository()).isEqualTo(ruleKey.repository()); + assertThat(hit.key().rule()).isEqualTo(ruleKey.rule()); + assertThat(hit.language()).isEqualTo("js"); + assertThat(hit.name()).isEqualTo("Rule S001"); + assertThat(hit.htmlDescription()).isEqualTo("Description S001"); + assertThat(hit.status()).isEqualTo(RuleStatus.READY); + //TODO fix date in ES +// assertThat(hit.createdAt()).isNotNull(); +// assertThat(hit.updatedAt()).isNotNull(); + assertThat(hit.internalKey()).isEqualTo("InternalKeyS001"); + assertThat(hit.severity()).isEqualTo("INFO"); + assertThat(hit.template()).isFalse(); //TODO assertThat((Collection) hit.getField(RuleNormalizer.RuleField.SYSTEM_TAGS.key())).isEmpty(); //TODO assertThat((Collection) hit.getField(RuleNormalizer.RuleField.TAGS.key())).isEmpty(); @@ -131,9 +127,9 @@ public class RuleServiceMediumTest { // verify that parameters are indexed in es index.refresh(); - Hit hit = index.getByKey(ruleKey); + Rule hit = index.getByKey(ruleKey); assertThat(hit).isNotNull(); - assertThat(hit.getField(RuleNormalizer.RuleField.PARAMS.key())).isNotNull(); + assertThat(hit.key()).isNotNull(); RuleService service = tester.get(RuleService.class); @@ -143,128 +139,6 @@ public class RuleServiceMediumTest { assertThat(Iterables.getLast(rule.params(), null).key()).isEqualTo("max"); } - @Test - public void insert_and_index_activeRules() throws InterruptedException { - DbSession dbSession = tester.get(MyBatis.class).openSession(false); - ActiveRuleDao activeRuleDao = tester.get(ActiveRuleDao.class); - - QualityProfileDto profileDto = new QualityProfileDto() - .setName("myprofile") - .setLanguage("java"); - qualityProfileDao.insert(profileDto, dbSession); - - // insert db - RuleKey ruleKey = RuleKey.of("javascript", "S001"); - RuleDto ruleDto = newRuleDto(ruleKey); - dao.insert(ruleDto, dbSession); - dbSession.commit(); - - ActiveRuleDto activeRule = new ActiveRuleDto() - .setInheritance("inherited") - .setProfileId(profileDto.getId()) - .setRuleId(ruleDto.getId()) - .setSeverity(Severity.BLOCKER); - - activeRuleDao.insert(activeRule, dbSession); - dbSession.commit(); - - dbSession.close(); - - // verify that activeRules are persisted in db - List persistedDtos = activeRuleDao.selectByRuleId(ruleDto.getId()); - assertThat(persistedDtos).hasSize(1); - - // verify that activeRules are indexed in es - index.refresh(); - - - Hit hit = index.getByKey(ruleKey); - assertThat(hit).isNotNull(); - assertThat(hit.getField(RuleNormalizer.RuleField.ACTIVE.key())).isNotNull(); - - Map activeRules = (Map) hit.getField(RuleNormalizer.RuleField.ACTIVE.key()); - assertThat(activeRules).hasSize(1); - } - - @Test - public void insert_and_index_activeRuleParams() throws InterruptedException { - DbSession dbSession = tester.get(MyBatis.class).openSession(false); - ActiveRuleDao activeRuleDao = tester.get(ActiveRuleDao.class); - - QualityProfileDto profileDto = new QualityProfileDto() - .setName("myprofile") - .setLanguage("java"); - qualityProfileDao.insert(profileDto, dbSession); - - // insert db - RuleKey ruleKey = RuleKey.of("javascript", "S001"); - RuleDto ruleDto = newRuleDto(ruleKey); - dao.insert(ruleDto, dbSession); - - RuleParamDto minParam = new RuleParamDto() - .setRuleId(ruleDto.getId()) - .setName("min") - .setType("STRING"); - dao.insert(minParam, dbSession); - - RuleParamDto maxParam = new RuleParamDto() - .setRuleId(ruleDto.getId()) - .setName("max") - .setType("STRING"); - dao.insert(maxParam, dbSession); - - - ActiveRuleDto activeRule = new ActiveRuleDto() - .setInheritance("inherited") - .setProfileId(profileDto.getId()) - .setRuleId(ruleDto.getId()) - .setSeverity(Severity.BLOCKER); - activeRuleDao.insert(activeRule, dbSession); - - ActiveRuleParamDto activeRuleMinParam = new ActiveRuleParamDto() - .setActiveRuleId(activeRule.getId()) - .setKey(minParam.getName()) - .setValue("minimum") - .setRulesParameterId(minParam.getId()); - activeRuleDao.insert(activeRuleMinParam, dbSession); - - ActiveRuleParamDto activeRuleMaxParam = new ActiveRuleParamDto() - .setActiveRuleId(activeRule.getId()) - .setKey(maxParam.getName()) - .setValue("maximum") - .setRulesParameterId(maxParam.getId()); - activeRuleDao.insert(activeRuleMaxParam, dbSession); - - dbSession.commit(); - dbSession.close(); - - // verify that activeRulesParams are persisted in db - List persistedDtos = activeRuleDao.selectParamsByActiveRuleId(activeRule.getId()); - assertThat(persistedDtos).hasSize(2); - - // verify that activeRulesParams are indexed in es - index.refresh(); - - Hit hit = index.getByKey(ruleKey); - assertThat(hit).isNotNull(); - - index.search(new RuleQuery(), new QueryOptions()); - - Map _activeRules = (Map) hit.getField(RuleNormalizer.RuleField.ACTIVE.key()); - assertThat(_activeRules).isNotNull().hasSize(1); - - Map _activeRule = (Map) Iterables.getFirst(_activeRules.values(),null); - assertThat(_activeRule.get(RuleNormalizer.RuleField.SEVERITY.key())).isEqualTo(Severity.BLOCKER); - - Map _activeRuleParams = (Map) _activeRule.get(RuleNormalizer.RuleField.PARAMS.key()); - assertThat(_activeRuleParams).isNotNull().hasSize(2); - - Map _activeRuleParamValue = (Map) _activeRuleParams.get(maxParam.getName()); - assertThat(_activeRuleParamValue).isNotNull().hasSize(1); - assertThat(_activeRuleParamValue.get(ActiveRuleNormalizer.ActiveRuleParamField.VALUE.key())).isEqualTo("maximum"); - - } - //TODO test delete, update, tags, params @Test @@ -319,9 +193,10 @@ public class RuleServiceMediumTest { // verify that tags are indexed in es index.search(new RuleQuery(), new QueryOptions()); - Hit hit = index.getByKey(ruleKey); + Rule hit = index.getByKey(ruleKey); assertThat(hit).isNotNull(); - assertThat(hit.getField(RuleNormalizer.RuleField.TAGS.key())).isNotNull(); + assertThat(hit.tags()).containsExactly("hello","world"); + assertThat(hit.systemTags()).containsExactly("AdMiN"); RuleService service = tester.get(RuleService.class); Rule rule = service.getByKey(ruleKey); -- 2.39.5