import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
-import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
public final class RuleDto implements Dto<RuleKey> {
return this;
}
- public List<String> getTags() {
+ public Set<String> getTags() {
return tags == null ?
- Collections.EMPTY_LIST :
- Arrays.asList(StringUtils.split(tags, ','));
+ Collections.EMPTY_SET :
+ new TreeSet<String>(Arrays.asList(StringUtils.split(tags, ',')));
}
- public List<String> getSystemTags() {
+ public Set<String> getSystemTags() {
return systemTags == null ?
- Collections.EMPTY_LIST :
- Arrays.asList(StringUtils.split(systemTags, ','));
+ Collections.EMPTY_SET :
+ new TreeSet<String>(Arrays.asList(StringUtils.split(systemTags, ',')));
}
private String getTagsField() {
systemTags = s;
}
- public RuleDto setTags(String[] tags) {
+ public RuleDto setTags(Set<String> tags) {
this.tags = StringUtils.join(tags, ',');
return this;
}
- public RuleDto setSystemTags(String[] tags) {
+ public RuleDto setSystemTags(Set<String> tags) {
this.systemTags = StringUtils.join(tags, ',');
return this;
}
*/
package org.sonar.server.rule2;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.server.debt.DebtRemediationFunction;
throw new IllegalStateException("Cannot parse date", e);
}
}
+
+ @Override
+ public String toString() {
+ return ReflectionToStringBuilder.toString(this);
+ }
}
@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);
this.addTermFilter(RuleField.KEY.key(), query.getKey(), fb);
+
+ this.addMultiFieldTermFilter(query.getTags(), fb, RuleField.TAGS.key(), RuleField.SYSTEM_TAGS.key());
+
if(query.getStatuses() != null && !query.getStatuses().isEmpty()) {
Collection<String> stringStatus = new ArrayList<String>();
for (RuleStatus status : query.getStatuses()) {
if((query.getLanguages() != null && !query.getLanguages().isEmpty()) ||
(query.getRepositories() != null && !query.getRepositories().isEmpty()) ||
(query.getSeverities() != null && !query.getSeverities().isEmpty()) ||
+ (query.getTags() != null && !query.getTags().isEmpty()) ||
(query.getStatuses() != null && !query.getStatuses().isEmpty()) ||
(query.getKey() != null && !query.getKey().isEmpty())) {
return fb;
import java.io.IOException;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
Result<R> result = new Result<R>(esResult);
- if(esResult != null){
+ if (esResult != null) {
result
.setTotal((int) esResult.getHits().totalHits())
.setTime(esResult.getTookInMillis());
protected abstract R getSearchResult(Map<String, Object> fields);
- protected R getSearchResult(SearchHit hit){
+ protected R getSearchResult(SearchHit hit) {
Map<String, Object> fields = new HashMap<String, Object>();
- for (Map.Entry<String, SearchHitField> field:hit.getFields().entrySet()){
- fields.put(field.getKey(),field.getValue().getValue());
+ for (Map.Entry<String, SearchHitField> field : hit.getFields().entrySet()) {
+ fields.put(field.getKey(), field.getValue().getValue());
}
return this.getSearchResult(fields);
}
/* ES QueryHelper Methods */
+
+ protected BoolFilterBuilder addMultiFieldTermFilter(Collection<String> values, BoolFilterBuilder filter, String... fields) {
+ if (values != null && !values.isEmpty()) {
+ BoolFilterBuilder valuesFilter = FilterBuilders.boolFilter();
+ for (String value : values) {
+ Collection<FilterBuilder> filterBuilders = new ArrayList<FilterBuilder>();
+ 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<String> values, BoolFilterBuilder filter) {
if (values != null && !values.isEmpty()) {
BoolFilterBuilder valuesFilter = FilterBuilders.boolFilter();
*/
package org.sonar.server.rule2;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.junit.After;
import org.junit.Before;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.rule.RuleDto;
-import org.sonar.server.search.Hit;
import org.sonar.server.search.QueryOptions;
import org.sonar.server.search.Result;
import org.sonar.server.tester.ServerTester;
assertThat(Iterables.getFirst(results.getHits(), null).key().rule()).isEqualTo("S002");
assertThat(Iterables.getLast(results.getHits(), null).key().rule()).isEqualTo("S001");
}
+ @Test
+ public void search_by_tag() {
+ dao.insert(newRuleDto(RuleKey.of("java", "S001")).setTags(ImmutableSet.of("tag1")), dbSession);
+ dao.insert(newRuleDto(RuleKey.of("java", "S002")).setTags(ImmutableSet.of("tag2")), dbSession);
+ dbSession.commit();
+ index.refresh();
+
+ // find all
+ RuleQuery query = new RuleQuery();
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+
+ // tag1 in query
+ query = new RuleQuery().setQueryText("tag1");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+ assertThat(Iterables.getFirst(index.search(query, new QueryOptions()).getHits(),null).tags()).containsExactly("tag1");
+
+ // tag1 and tag2 in query
+ query = new RuleQuery().setQueryText("tag1 tag2");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+
+ // tag2 in filter
+ query = new RuleQuery().setTags(ImmutableSet.of("tag2"));
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+ assertThat(Iterables.getFirst(index.search(query, new QueryOptions()).getHits(),null).tags()).containsExactly("tag2");
+
+ // tag2 in filter and tag1 tag2 in query
+ query = new RuleQuery().setTags(ImmutableSet.of("tag2")).setQueryText("tag1");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(0);
+
+ // tag2 in filter and tag1 in query
+ query = new RuleQuery().setTags(ImmutableSet.of("tag2")).setQueryText("tag1 tag2");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+ assertThat(Iterables.getFirst(index.search(query, new QueryOptions()).getHits(),null).tags()).containsExactly("tag2");
+
+ // null list => no filter
+ query = new RuleQuery().setTags(Collections.<String>emptySet());
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+
+ // null list => no filter
+ query = new RuleQuery().setTags(null);
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+ }
@Test
public void paging() {
*/
package org.sonar.server.rule2;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.junit.After;
import org.junit.Before;
.setSeverity(Severity.INFO)
.setCardinality(Cardinality.SINGLE)
.setLanguage("js")
+ .setTags(ImmutableSet.of("tag1", "tag2"))
+ .setSystemTags(ImmutableSet.of("systag1", "systag2"))
.setRemediationFunction("linear")
.setDefaultRemediationFunction("linear_offset")
.setRemediationCoefficient("1h")
.setRemediationOffset("5min")
.setDefaultRemediationOffset("10h")
.setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix")
- .setTags(new String[]{"tag1", "tag2"})
- .setSystemTags(new String[]{"systag1", "systag2"})
.setCreatedAt(DateUtils.parseDate("2013-12-16"))
.setUpdatedAt(DateUtils.parseDate("2013-12-17"));
}