diff options
8 files changed, 111 insertions, 11 deletions
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 9c725a979a7..c88d7a7158c 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 @@ -417,6 +417,10 @@ measure_filter.criteria.name=Name measure_filter.criteria.language=Language measure_filter.criteria.metric=Metric measure_filter.criteria.project=Project +measure_filter.criteria.alert=Alert +measure_filter.criteria.alert.error=Error +measure_filter.criteria.alert.warn=Warning +measure_filter.criteria.alert.ok=Ok measure_filter.criteria.from_date=Inspected since measure_filter.criteria.to_date=Inspected before measure_filter.criteria.date_format=year-month-day (2013-01-31) @@ -430,6 +434,7 @@ measure_filter.new_search=New search measure_filter.favourite_filters=Favourite Filters measure_filter.more_criteria=+ More Criteria measure_filter.languages=Languages +measure_filter.alert_levels=Alert levels measure_filter.col.date=Date measure_filter.col.description=Description measure_filter.col.key=Key diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilter.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilter.java index 1dcbcd66021..67108a4eb31 100644 --- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilter.java +++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilter.java @@ -196,12 +196,12 @@ public class MeasureFilter { } public boolean isEmpty() { - return resourceQualifiers.isEmpty() && resourceScopes.isEmpty() && StringUtils.isEmpty(baseResourceKey) && baseResourceId==null && !userFavourites; + return resourceQualifiers.isEmpty() && resourceScopes.isEmpty() && StringUtils.isEmpty(baseResourceKey) && baseResourceId == null && !userFavourites; } @VisibleForTesting static List<String> sanitize(@Nullable List<String> list) { - return isEmptyList(list) ? Collections.<String>emptyList() : Lists.newArrayList(list); + return isEmptyList(list) ? Collections.<String> emptyList() : Lists.newArrayList(list); } private static boolean isEmptyList(@Nullable List<String> list) { diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java index 39f5903f884..bbf2c7ed869 100644 --- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java +++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java @@ -25,7 +25,7 @@ import org.sonar.api.measures.Metric; public class MeasureFilterCondition { public enum Operator { - EQUALS("eq", "="), GREATER("gt", ">"), GREATER_OR_EQUALS("gte", ">="), LESS("lt", "<"), LESS_OR_EQUALS("lte", "<="); + EQUALS("eq", "="), GREATER("gt", ">"), GREATER_OR_EQUALS("gte", ">="), LESS("lt", "<"), LESS_OR_EQUALS("lte", "<="), IN("in", "IN"); private String code; private String sql; @@ -52,12 +52,21 @@ public class MeasureFilterCondition { private final Metric metric; private final Operator operator; private final double value; + private final String textValue; private Integer period = null; public MeasureFilterCondition(Metric metric, Operator operator, double value) { this.metric = metric; this.operator = operator; this.value = value; + this.textValue = null; + } + + public MeasureFilterCondition(Metric metric, Operator operator, String textValue) { + this.metric = metric; + this.operator = operator; + this.value = 0; + this.textValue = textValue; } public MeasureFilterCondition setPeriod(Integer period) { @@ -77,6 +86,10 @@ public class MeasureFilterCondition { return value; } + public String textValue() { + return textValue; + } + public Integer period() { return period; } @@ -85,8 +98,10 @@ public class MeasureFilterCondition { sb.append("pmcond").append(conditionIndex); if (period != null) { sb.append(".variation_value_").append(period).toString(); - } else { + } else if (textValue == null) { sb.append(".value"); + } else { + sb.append(".text_value"); } return sb; } @@ -97,7 +112,13 @@ public class MeasureFilterCondition { sql.append(metric.getId()); sql.append(" AND "); appendSqlColumn(sql, conditionIndex); - sql.append(operator.getSql()).append(value); + sql.append(" ").append(operator.getSql()).append(" "); + if (textValue == null) { + sql.append(value); + } + else { + sql.append(textValue); + } sql.append(" AND "); sql.append(table).append(".rule_id IS NULL AND "); sql.append(table).append(".rule_priority IS NULL AND "); diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterFactory.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterFactory.java index 08d0cc043c9..ce0ca32382e 100644 --- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterFactory.java +++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterFactory.java @@ -19,9 +19,13 @@ */ package org.sonar.core.measure; +import com.google.common.base.Function; +import com.google.common.base.Joiner; import com.google.common.base.Strings; +import com.google.common.collect.Lists; import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; +import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.measures.MetricFinder; import org.sonar.api.utils.DateUtils; @@ -51,6 +55,10 @@ public class MeasureFilterFactory implements ServerComponent { filter.setResourceScopes(toList(properties.get("scopes"))); filter.setResourceQualifiers(toList(properties.get("qualifiers"))); filter.setResourceLanguages(toList(properties.get("languages"))); + MeasureFilterCondition condition = alertToCondition((toList(properties.get("alertLevels")))); + if (condition != null) { + filter.addCondition(condition); + } if (properties.containsKey("onBaseComponents")) { filter.setOnBaseResourceChildren(Boolean.valueOf((String) properties.get("onBaseComponents"))); } @@ -126,6 +134,28 @@ public class MeasureFilterFactory implements ServerComponent { return condition; } + private MeasureFilterCondition alertToCondition(List<String> alertLevels) { + if (alertLevels == null || alertLevels.isEmpty()) { + return null; + } + MeasureFilterCondition condition = null; + String metricKey = CoreMetrics.ALERT_STATUS_KEY; + String op = "in"; + List<String> alertLevelsUppercase = Lists.transform(alertLevels, new Function<String, String>() { + @Override + public String apply(String input) { + return input != null ? input.toUpperCase() : ""; + } + }); + String val = "(\"" + Joiner.on("\", \"").join(alertLevelsUppercase) + "\")"; + if (!Strings.isNullOrEmpty(metricKey) && !Strings.isNullOrEmpty(op) && !Strings.isNullOrEmpty(val)) { + Metric metric = metricFinder.findByKey(metricKey); + MeasureFilterCondition.Operator operator = MeasureFilterCondition.Operator.fromCode(op); + condition = new MeasureFilterCondition(metric, operator, val); + } + return condition; + } + private List<String> toList(@Nullable Object obj) { List<String> result = null; if (obj != null) { diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java index 6b8b877b285..8545d98be8f 100644 --- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java +++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java @@ -211,8 +211,8 @@ class MeasureFilterSql { private static void appendInStatement(List<String> values, StringBuilder to) { to.append(" ("); - for (int i=0 ; i<values.size() ; i++) { - if (i>0) { + for (int i = 0; i < values.size(); i++) { + if (i > 0) { to.append(","); } to.append("'"); diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java index 656660d1ffb..a6bfdee3a17 100644 --- a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java +++ b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java @@ -59,9 +59,10 @@ public class MeasureFilterConditionTest { assertThat(condition.operator()).isEqualTo(MeasureFilterCondition.Operator.GREATER); assertThat(condition.period()).isNull(); assertThat(condition.value()).isEqualTo(10.0); + assertThat(condition.textValue()).isNull(); assertThat(condition.appendSqlColumn(new StringBuilder(), 1).toString()).isEqualTo("pmcond1.value"); assertThat(condition.toString()).isNotEmpty(); - assertThat(condition.appendSqlCondition(new StringBuilder(), 1).toString()).isEqualTo(" pmcond1.metric_id=123 AND pmcond1.value>10.0 AND pmcond1.rule_id IS NULL AND pmcond1.rule_priority IS NULL AND pmcond1.characteristic_id IS NULL AND pmcond1.person_id IS NULL "); + assertThat(condition.appendSqlCondition(new StringBuilder(), 1).toString()).isEqualTo(" pmcond1.metric_id=123 AND pmcond1.value > 10.0 AND pmcond1.rule_id IS NULL AND pmcond1.rule_priority IS NULL AND pmcond1.characteristic_id IS NULL AND pmcond1.person_id IS NULL "); } @Test @@ -77,6 +78,22 @@ public class MeasureFilterConditionTest { assertThat(condition.value()).isEqualTo(10.0); assertThat(condition.appendSqlColumn(new StringBuilder(), 2).toString()).isEqualTo("pmcond2.variation_value_3"); assertThat(condition.toString()).isNotEmpty(); - assertThat(condition.appendSqlCondition(new StringBuilder(), 2).toString()).isEqualTo(" pmcond2.metric_id=123 AND pmcond2.variation_value_3<=10.0 AND pmcond2.rule_id IS NULL AND pmcond2.rule_priority IS NULL AND pmcond2.characteristic_id IS NULL AND pmcond2.person_id IS NULL "); + assertThat(condition.appendSqlCondition(new StringBuilder(), 2).toString()).isEqualTo(" pmcond2.metric_id=123 AND pmcond2.variation_value_3 <= 10.0 AND pmcond2.rule_id IS NULL AND pmcond2.rule_priority IS NULL AND pmcond2.characteristic_id IS NULL AND pmcond2.person_id IS NULL "); + } + + @Test + public void text_value_condition() { + Metric ncloc = new Metric.Builder("ncloc", "NCLOC", Metric.ValueType.INT).create(); + ncloc.setId(123); + MeasureFilterCondition condition = new MeasureFilterCondition(ncloc, MeasureFilterCondition.Operator.EQUALS, "\"foo\""); + + assertThat(condition.metric()).isEqualTo(ncloc); + assertThat(condition.operator()).isEqualTo(MeasureFilterCondition.Operator.EQUALS); + assertThat(condition.period()).isNull(); + assertThat(condition.value()).isEqualTo(0); + assertThat(condition.textValue()).isEqualTo("\"foo\""); + assertThat(condition.appendSqlColumn(new StringBuilder(), 1).toString()).isEqualTo("pmcond1.text_value"); + assertThat(condition.toString()).isNotEmpty(); + assertThat(condition.appendSqlCondition(new StringBuilder(), 1).toString()).isEqualTo(" pmcond1.metric_id=123 AND pmcond1.text_value = \"foo\" AND pmcond1.rule_id IS NULL AND pmcond1.rule_priority IS NULL AND pmcond1.characteristic_id IS NULL AND pmcond1.person_id IS NULL "); } } diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java index ac5210d01db..c6f1da2e8e0 100644 --- a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java +++ b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java @@ -28,6 +28,7 @@ import org.sonar.api.measures.Metric; import org.sonar.api.measures.MetricFinder; import org.sonar.api.utils.DateUtils; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -174,6 +175,23 @@ public class MeasureFilterFactoryTest { } @Test + public void alert_level_condition() { + MeasureFilterFactory factory = new MeasureFilterFactory(newMetricFinder()); + Map<String, Object> props = ImmutableMap.<String, Object>of( + "alertLevels", Arrays.asList("error", "warn") + ); + MeasureFilter filter = factory.create(props); + + List<MeasureFilterCondition> conditions = filter.getMeasureConditions(); + assertThat(conditions).hasSize(1); + assertThat(conditions.get(0).metric().getKey()).isEqualTo("alert_status"); + assertThat(conditions.get(0).operator()).isEqualTo(MeasureFilterCondition.Operator.IN); + assertThat(conditions.get(0).value()).isEqualTo(0); + assertThat(conditions.get(0).textValue()).isEqualTo("(\"ERROR\", \"WARN\")"); + assertThat(conditions.get(0).period()).isNull(); + } + + @Test public void ignore_partial_measure_condition() { MeasureFilterFactory factory = new MeasureFilterFactory(newMetricFinder()); Map<String, Object> props = ImmutableMap.<String, Object>of( diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_sidebar.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_sidebar.html.erb index 78a91d4620b..eca9640c027 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_sidebar.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/measures/_sidebar.html.erb @@ -28,13 +28,14 @@ var hiddenConditionIndexes = [<%= hidden_condition_indexes.join(',') -%>]; $j(document).ready(function () { $j('#select-lang').select2({allowClear: true, width: '100%', placeholder: '<%= escape_javascript message 'measure_filter.languages' -%>'}); + $j('#select-alert').select2({allowClear: true, width: '100%', placeholder: '<%= escape_javascript message 'measure_filter.alert_levels' -%>'}); $j('#select-qualifiers').select2({allowClear: true, width: '100%', placeholder: '<%= escape_javascript message('measure_filter.criteria.what') -%>'}); $j('#more-criteria') .select2({allowClear: true, width: '100%', placeholder: '<%= message 'measure_filter.more_criteria' -%>'}) .on("change", function (e) { $j("#criteria-" + e.val).insertBefore($j("#more-td")).show(); - if (e.val == 'lang' || e.val == 'project') { + if (e.val == 'lang' || e.val == 'project' || e.val == 'alert') { $j("#select-" + e.val).select2("enable"); $j("#select-" + e.val).select2("focus"); } else if (e.val == 'fav') { @@ -140,6 +141,11 @@ <%= check_box_tag 'onFavourites', 'true', @filter.criteria['onFavourites']=='true', :id => 'check-fav' -%> </li> + <li id="criteria-alert" <%= "style='display:none'" unless @filter.criteria('alertLevels') -%> class="marginbottom5"> + <% alertLevels = [['', '']].concat(['error', 'warn', 'ok'].map { |level| [message('measure_filter.criteria.alert.' + level), level] }) %> + <%= select_tag 'alertLevels[]', options_for_select(alertLevels, @filter.criteria['alertLevels']), :multiple => true, :id => 'select-alert' -%> + </li> + <% condition_metrics = Metric.all.select { |m| m.numeric? && !m.hidden } for i in 1..3 @@ -212,6 +218,9 @@ <% unless @filter.base_resource %> <option value="project"><%= message 'measure_filter.criteria.components_of_project' -%></option> <% end %> + <% unless @filter.criteria('alertLevels') %> + <option value="alert"><%= message 'measure_filter.criteria.alert' -%></option> + <% end %> </select> </li> <li> @@ -221,4 +230,4 @@ <% end %> </li> </form> -</ul>
\ No newline at end of file +</ul> |