This is the first step before the refactoring of the tables FILTERS, FILTER_COLUMNS and CRITERIA
<level value="WARN"/>
</logger>
+ <logger name="org.sonar.MEASURE_FILTER">
+ <level value="WARN"/>
+ </logger>
+
<root>
<level value="INFO"/>
<appender-ref ref="SONAR_FILE"/>
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
-
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1.1</version>
+ </dependency>
<!-- logging -->
<dependency>
package org.sonar.core.measure;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import org.sonar.api.measures.Metric;
+import javax.annotation.Nullable;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
-import java.util.Set;
public class MeasureFilter {
// conditions on resources
private String baseResourceKey;
- private boolean onBaseResourceChildren = false; // only if baseResourceKey is set
- private Set<String> resourceScopes = Sets.newHashSet();
- private Set<String> resourceQualifiers = Sets.newHashSet();
- private Set<String> resourceLanguages = Sets.newHashSet();
+ private boolean onBaseResourceChildren = false; // only if getBaseResourceKey is set
+ private List<String> resourceScopes = Lists.newArrayList();
+ private List<String> resourceQualifiers = Lists.newArrayList();
+ private List<String> resourceLanguages = Lists.newArrayList();
private String resourceName;
private Date fromDate = null, toDate = null;
private boolean userFavourites = false;
// conditions on measures
- private List<MeasureFilterValueCondition> measureConditions = Lists.newArrayList();
+ private List<MeasureFilterCondition> measureConditions = Lists.newArrayList();
// sort
private MeasureFilterSort sort = new MeasureFilterSort();
- public String baseResourceKey() {
+ public String getBaseResourceKey() {
return baseResourceKey;
}
return onBaseResourceChildren;
}
- public MeasureFilter setResourceScopes(Set<String> resourceScopes) {
- this.resourceScopes = resourceScopes;
+ public MeasureFilter setResourceScopes(@Nullable List<String> l) {
+ this.resourceScopes = (l != null ? l : Collections.<String>emptyList());
return this;
}
- public MeasureFilter setResourceQualifiers(String... qualifiers) {
- this.resourceQualifiers = Sets.newHashSet(qualifiers);
+ public MeasureFilter setResourceQualifiers(List<String> l) {
+ this.resourceQualifiers = (l != null ? l : Collections.<String>emptyList());
return this;
}
- public MeasureFilter setResourceLanguages(String... languages) {
- this.resourceLanguages = Sets.newHashSet(languages);
+ public MeasureFilter setResourceQualifiers(String... l) {
+ this.resourceQualifiers = Lists.newArrayList(l);
+ return this;
+ }
+
+ public MeasureFilter setResourceLanguages(List<String> l) {
+ this.resourceLanguages = (l != null ? l : Collections.<String>emptyList());
+ return this;
+ }
+
+ public MeasureFilter setResourceLanguages(String... l) {
+ this.resourceLanguages = Lists.newArrayList(l);
return this;
}
return this;
}
- public boolean userFavourites() {
+ public boolean isOnFavourites() {
return userFavourites;
}
- public String resourceName() {
+ public String getResourceName() {
return resourceName;
}
return this;
}
- public MeasureFilter addCondition(MeasureFilterValueCondition condition) {
+ public MeasureFilter addCondition(MeasureFilterCondition condition) {
this.measureConditions.add(condition);
return this;
}
}
public MeasureFilter setSortOnMetric(Metric m) {
+ this.sort.setField(MeasureFilterSort.Field.METRIC);
this.sort.setMetric(m);
return this;
}
return this;
}
- public Date fromDate() {
+ public Date getFromDate() {
return fromDate;
}
- public Date toDate() {
+ public Date getToDate() {
return toDate;
}
- public Set<String> resourceScopes() {
+ public List<String> getResourceScopes() {
return resourceScopes;
}
- public Set<String> resourceQualifiers() {
+ public List<String> getResourceQualifiers() {
return resourceQualifiers;
}
- public Set<String> resourceLanguages() {
+ public List<String> getResourceLanguages() {
return resourceLanguages;
}
- public List<MeasureFilterValueCondition> measureConditions() {
+ public List<MeasureFilterCondition> getMeasureConditions() {
return measureConditions;
}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import org.sonar.api.measures.Metric;
+
+public class MeasureFilterCondition {
+
+ private final Metric metric;
+ private final String operator;
+ private final double value;
+ private Integer period = null;
+
+ public MeasureFilterCondition(Metric metric, String operator, double value) {
+ this.metric = metric;
+ this.operator = operator;
+ this.value = value;
+ }
+
+ public MeasureFilterCondition setPeriod(Integer period) {
+ this.period = period;
+ return this;
+ }
+
+ public Metric metric() {
+ return metric;
+ }
+
+ public String operator() {
+ return operator;
+ }
+
+ public double value() {
+ return value;
+ }
+
+ public Integer period() {
+ return period;
+ }
+
+ String valueColumn() {
+ if (period != null) {
+ return "pm.variation_value_" + period;
+ }
+ return "pm.value";
+ }
+
+ void appendSqlCondition(StringBuilder sql) {
+ sql.append(" pm.metric_id=");
+ sql.append(metric.getId());
+ sql.append(" AND ").append(valueColumn()).append(operator).append(value);
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.sonar.core.resource.SnapshotDto;
+
+class MeasureFilterContext {
+ private Long userId;
+ private SnapshotDto baseSnapshot;
+ private String sql;
+ private String json;
+
+ Long getUserId() {
+ return userId;
+ }
+
+ MeasureFilterContext setUserId(Long userId) {
+ this.userId = userId;
+ return this;
+ }
+
+ SnapshotDto getBaseSnapshot() {
+ return baseSnapshot;
+ }
+
+ MeasureFilterContext setBaseSnapshot(SnapshotDto baseSnapshot) {
+ this.baseSnapshot = baseSnapshot;
+ return this;
+ }
+
+ String getSql() {
+ return sql;
+ }
+
+ MeasureFilterContext setSql(String sql) {
+ this.sql = sql;
+ return this;
+ }
+
+ String getJson() {
+ return json;
+ }
+
+ MeasureFilterContext setJson(String json) {
+ this.json = json;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
+ .append("json", json)
+ .append("sql", sql)
+ .append("user", userId)
+ .toString();
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.MetricFinder;
+import org.sonar.api.utils.DateUtils;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+public class MeasureFilterDecoder implements ServerComponent {
+ private MetricFinder metricFinder;
+ private JSONParser parser = new JSONParser();
+
+ public MeasureFilterDecoder(MetricFinder metricFinder) {
+ this.metricFinder = metricFinder;
+ }
+
+ public MeasureFilter decode(String text) throws ParseException {
+ MeasureFilter filter = new MeasureFilter();
+ JSONObject map = (JSONObject) parser.parse(text);
+ parseResourceConditions(filter, map);
+ parseMeasureConditions(map, filter);
+ parseSorting(map, filter);
+ return filter;
+ }
+
+ private void parseResourceConditions(MeasureFilter filter, JSONObject map) {
+ filter.setBaseResourceKey((String) map.get("base"));
+ if (map.containsKey("onBaseChildren")) {
+ filter.setOnBaseResourceChildren(((Boolean) map.get("onBaseChildren")).booleanValue());
+ }
+ filter.setResourceScopes((List<String>) map.get("scopes"));
+ filter.setResourceQualifiers((List<String>) map.get("qualifiers"));
+ filter.setResourceLanguages((List<String>) map.get("languages"));
+ filter.setResourceName((String) map.get("name"));
+
+ if (map.containsKey("fromDate")) {
+ filter.setFromDate(toDate(map, "fromDate"));
+ }
+ if (map.containsKey("afterDays")) {
+ filter.setFromDate(toDays(map, "afterDays"));
+ }
+ if (map.containsKey("toDate")) {
+ filter.setToDate(toDate(map, "toDate"));
+ }
+ if (map.containsKey("beforeDays")) {
+ filter.setToDate(toDays(map, "beforeDays"));
+ }
+ if (map.containsKey("favourites")) {
+ filter.setUserFavourites(((Boolean) map.get("favourites")).booleanValue());
+ }
+ }
+
+ private void parseSorting(JSONObject map, MeasureFilter filter) {
+ if (map.containsKey("sortAsc")) {
+ filter.setSortAsc(((Boolean) map.get("sortAsc")).booleanValue());
+ }
+ String s = (String) map.get("sortField");
+ if (s != null) {
+ filter.setSortOn(MeasureFilterSort.Field.valueOf(s));
+ }
+ s = (String) map.get("sortField");
+ if (s != null) {
+ filter.setSortOn(MeasureFilterSort.Field.valueOf((String) map.get("sortField")));
+ }
+ s = (String) map.get("sortMetric");
+ if (s != null) {
+ filter.setSortOnMetric(metricFinder.findByKey(s));
+ }
+ if (map.containsKey("sortPeriod")) {
+ filter.setSortOnPeriod(((Long) map.get("sortPeriod")).intValue());
+ }
+ }
+
+ private void parseMeasureConditions(JSONObject map, MeasureFilter filter) {
+ JSONArray conditions = (JSONArray) map.get("conditions");
+ if (conditions != null) {
+ for (Object obj : conditions) {
+ JSONObject c = (JSONObject) obj;
+ Metric metric = metricFinder.findByKey((String) c.get("metric"));
+ String operator = (String) c.get("op");
+ Double value = (Double) c.get("val");
+ MeasureFilterCondition condition = new MeasureFilterCondition(metric, operator, value);
+ if (c.containsKey("period")) {
+ condition.setPeriod(((Long) c.get("period")).intValue());
+ }
+ filter.addCondition(condition);
+ }
+ }
+ }
+
+ private static Date toDate(JSONObject map, String key) {
+ String date = (String) map.get(key);
+ if (date != null) {
+ return DateUtils.parseDate(date);
+ }
+ return null;
+ }
+
+ private static Date toDays(JSONObject map, String key) {
+ int days = ((Long) map.get(key)).intValue();
+ Date date = org.apache.commons.lang.time.DateUtils.truncate(new Date(), Calendar.DATE);
+ date = org.apache.commons.lang.time.DateUtils.addDays(date, -days);
+ return date;
+ }
+
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.lang.SystemUtils;
+import org.json.simple.parser.ParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.ServerComponent;
+
+import javax.annotation.Nullable;
+import java.util.List;
+
+public class MeasureFilterEngine implements ServerComponent {
+ private static final Logger FILTER_LOG = LoggerFactory.getLogger("org.sonar.MEASURE_FILTER");
+
+ private final MeasureFilterDecoder decoder;
+ private final MeasureFilterExecutor executor;
+
+ public MeasureFilterEngine(MeasureFilterDecoder decoder, MeasureFilterExecutor executor) {
+ this.decoder = decoder;
+ this.executor = executor;
+ }
+
+ public List<MeasureFilterRow> execute(String filterJson, @Nullable Long userId) throws ParseException {
+ return execute(filterJson, userId, FILTER_LOG);
+ }
+
+ @VisibleForTesting
+ List<MeasureFilterRow> execute(String filterJson, @Nullable Long userId, Logger logger) {
+ MeasureFilterContext context = new MeasureFilterContext();
+ context.setJson(filterJson);
+ context.setUserId(userId);
+ try {
+ long start = System.currentTimeMillis();
+ MeasureFilter filter = decoder.decode(filterJson);
+ List<MeasureFilterRow> rows = executor.execute(filter, context);
+ log(context, rows, (System.currentTimeMillis() - start), logger);
+ return rows;
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to execute filter: " + context, e);
+ }
+ }
+
+ private void log(MeasureFilterContext context, List<MeasureFilterRow> rows, long durationMs, Logger logger) {
+ if (logger.isDebugEnabled()) {
+ StringBuilder log = new StringBuilder();
+ log.append(SystemUtils.LINE_SEPARATOR);
+ log.append(" json: ").append(context.getJson()).append(SystemUtils.LINE_SEPARATOR);
+ log.append(" sql: ").append(context.getSql()).append(SystemUtils.LINE_SEPARATOR);
+ log.append("results: ").append(rows.size()).append(" rows in ").append(durationMs).append("ms").append(SystemUtils.LINE_SEPARATOR);
+ logger.debug(log.toString());
+ }
+ }
+
+}
package org.sonar.core.measure;
import org.apache.ibatis.session.SqlSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.resource.ResourceDao;
-import javax.annotation.Nullable;
import java.sql.Connection;
+import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
public class MeasureFilterExecutor implements ServerComponent {
- private static final Logger FILTER_LOG = LoggerFactory.getLogger("org.sonar.MEASURE_FILTER");
private MyBatis mybatis;
private Database database;
this.resourceDao = resourceDao;
}
- public List<MeasureFilterRow> execute(MeasureFilter filter, @Nullable Long userId) {
+ public List<MeasureFilterRow> execute(MeasureFilter filter, MeasureFilterContext context) throws SQLException {
List<MeasureFilterRow> rows;
SqlSession session = null;
try {
session = mybatis.openSession();
- MesasureFilterContext context = prepareContext(filter, userId, session);
+ prepareContext(context, filter, session);
if (isValid(filter, context)) {
MeasureFilterSql sql = new MeasureFilterSql(database, filter, context);
+ context.setSql(sql.sql());
Connection connection = session.getConnection();
rows = sql.execute(connection);
} else {
rows = Collections.emptyList();
}
-
- } catch (Exception e) {
- throw new IllegalStateException(e);
-
} finally {
MyBatis.closeQuietly(session);
}
return rows;
}
- private MesasureFilterContext prepareContext(MeasureFilter filter, Long userId, SqlSession session) {
- MesasureFilterContext context = new MesasureFilterContext();
- context.setUserId(userId);
- if (filter.baseResourceKey() != null) {
- context.setBaseSnapshot(resourceDao.getLastSnapshot(filter.baseResourceKey(), session));
+
+ private void prepareContext(MeasureFilterContext context, MeasureFilter filter, SqlSession session) {
+ if (filter.getBaseResourceKey() != null) {
+ context.setBaseSnapshot(resourceDao.getLastSnapshot(filter.getBaseResourceKey(), session));
}
- return context;
}
- static boolean isValid(MeasureFilter filter, MesasureFilterContext context) {
- return
- !(filter.resourceQualifiers().isEmpty() && !filter.userFavourites()) &&
+ static boolean isValid(MeasureFilter filter, MeasureFilterContext context) {
+ boolean valid =
!(filter.isOnBaseResourceChildren() && context.getBaseSnapshot() == null) &&
- !(filter.userFavourites() && context.getUserId() == null);
+ !(filter.isOnFavourites() && context.getUserId() == null);
+ for (MeasureFilterCondition condition : filter.getMeasureConditions()) {
+ if (condition.period() != null && condition.period() < 1) {
+ valid = false;
+ }
+ if (condition.metric() == null) {
+ valid = false;
+ }
+ }
+ if (filter.sort().getPeriod() != null && filter.sort().getPeriod() < 1) {
+ valid = false;
+ }
+ if (filter.sort().onMeasures() && filter.sort().metric() == null) {
+ valid = false;
+ }
+ return valid;
}
}
private Field field = Field.NAME;
private Metric metric = null;
- private int period = -1;
+ private Integer period = null;
private boolean asc = true;
MeasureFilterSort() {
this.metric = metric;
}
- void setPeriod(int period) {
- this.period = (period > 0 ? period : -1);
+ Integer getPeriod() {
+ return period;
+ }
+
+ void setPeriod(Integer period) {
+ this.period = period;
}
void setAsc(boolean asc) {
break;
case METRIC:
if (metric.isNumericType()) {
- column = (period > 0 ? "pm.variation_value_" + period : "pm.value");
+ column = (period != null ? "pm.variation_value_" + period : "pm.value");
} else {
column = "pm.text_value";
}
private final Database database;
private final MeasureFilter filter;
- private final MesasureFilterContext context;
+ private final MeasureFilterContext context;
private final StringBuilder sql = new StringBuilder(1000);
private final List<Date> dateParameters = Lists.newArrayList();
- MeasureFilterSql(Database database, MeasureFilter filter, MesasureFilterContext context) {
+ MeasureFilterSql(Database database, MeasureFilter filter, MeasureFilterContext context) {
this.database = database;
this.filter = filter;
this.context = context;
private void init() {
sql.append("SELECT block.id, max(block.rid) rid, max(block.rootid) rootid, max(sortval) sortval");
- for (int index = 0; index < filter.measureConditions().size(); index++) {
+ for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
sql.append(", max(crit_").append(index).append(")");
}
sql.append(" FROM (");
appendSortBlock();
- for (int index = 0; index < filter.measureConditions().size(); index++) {
- MeasureFilterValueCondition condition = filter.measureConditions().get(index);
+ for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
+ MeasureFilterCondition condition = filter.getMeasureConditions().get(index);
sql.append(" UNION ");
appendConditionBlock(index, condition);
}
sql.append(") block GROUP BY block.id");
- if (!filter.measureConditions().isEmpty()) {
+ if (!filter.getMeasureConditions().isEmpty()) {
sql.append(" HAVING ");
- for (int index = 0; index < filter.measureConditions().size(); index++) {
+ for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
if (index > 0) {
sql.append(" AND ");
}
private void appendSortBlock() {
sql.append(" SELECT s.id, s.project_id rid, s.root_project_id rootid, ").append(filter.sort().column()).append(" sortval");
- for (int index = 0; index < filter.measureConditions().size(); index++) {
- MeasureFilterValueCondition condition = filter.measureConditions().get(index);
+ for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
+ MeasureFilterCondition condition = filter.getMeasureConditions().get(index);
sql.append(", ").append(nullSelect(condition.metric())).append(" crit_").append(index);
}
sql.append(" FROM snapshots s INNER JOIN projects p ON s.project_id=p.id ");
appendResourceConditions();
}
- private void appendConditionBlock(int conditionIndex, MeasureFilterValueCondition condition) {
+ private void appendConditionBlock(int conditionIndex, MeasureFilterCondition condition) {
sql.append(" SELECT s.id, s.project_id rid, s.root_project_id rootid, null sortval");
- for (int j = 0; j < filter.measureConditions().size(); j++) {
+ for (int j = 0; j < filter.getMeasureConditions().size(); j++) {
sql.append(", ");
if (j == conditionIndex) {
sql.append(condition.valueColumn());
} else {
- sql.append(nullSelect(filter.measureConditions().get(j).metric()));
+ sql.append(nullSelect(filter.getMeasureConditions().get(j).metric()));
}
sql.append(" crit_").append(j);
}
sql.append(" WHERE ");
appendResourceConditions();
sql.append(" AND pm.rule_id IS NULL AND pm.rule_priority IS NULL AND pm.characteristic_id IS NULL AND pm.person_id IS NULL AND ");
- condition.appendSql(sql);
+ condition.appendSqlCondition(sql);
}
private void appendResourceConditions() {
sql.append(" s.status='P' AND s.islast=").append(database.getDialect().getTrueSqlValue());
- sql.append(" AND p.copy_resource_id IS NULL ");
- if (!filter.resourceQualifiers().isEmpty()) {
+ if (context.getBaseSnapshot() == null) {
+ sql.append(" AND p.copy_resource_id IS NULL ");
+ }
+ if (!filter.getResourceQualifiers().isEmpty()) {
sql.append(" AND s.qualifier IN ");
- appendInStatement(filter.resourceQualifiers(), sql);
+ appendInStatement(filter.getResourceQualifiers(), sql);
}
- if (!filter.resourceScopes().isEmpty()) {
+ if (!filter.getResourceScopes().isEmpty()) {
sql.append(" AND s.scope IN ");
- appendInStatement(filter.resourceScopes(), sql);
+ appendInStatement(filter.getResourceScopes(), sql);
}
- if (!filter.resourceLanguages().isEmpty()) {
+ if (!filter.getResourceLanguages().isEmpty()) {
sql.append(" AND p.language IN ");
- appendInStatement(filter.resourceLanguages(), sql);
+ appendInStatement(filter.getResourceLanguages(), sql);
}
- if (filter.fromDate() != null) {
+ if (filter.getFromDate() != null) {
sql.append(" AND s.created_at >= ? ");
- dateParameters.add(new java.sql.Date(filter.fromDate().getTime()));
+ dateParameters.add(new java.sql.Date(filter.getFromDate().getTime()));
}
- if (filter.toDate() != null) {
+ if (filter.getToDate() != null) {
sql.append(" AND s.created_at <= ? ");
- dateParameters.add(new java.sql.Date(filter.toDate().getTime()));
+ dateParameters.add(new java.sql.Date(filter.getToDate().getTime()));
}
- if (filter.userFavourites() && context.getUserId() != null) {
+ if (filter.isOnFavourites() && context.getUserId() != null) {
sql.append(" AND s.project_id IN (SELECT props.resource_id FROM properties props WHERE props.prop_key='favourite' AND props.user_id=");
sql.append(context.getUserId());
sql.append(" AND props.resource_id IS NOT NULL) ");
}
- if (StringUtils.isNotBlank(filter.resourceName())) {
+ if (StringUtils.isNotBlank(filter.getResourceName())) {
sql.append(" AND s.project_id IN (SELECT rindex.resource_id FROM resource_index rindex WHERE rindex.kee like '");
- sql.append(StringEscapeUtils.escapeSql(StringUtils.lowerCase(filter.resourceName())));
+ sql.append(StringEscapeUtils.escapeSql(StringUtils.lowerCase(filter.getResourceName())));
sql.append("%'");
- if (!filter.resourceQualifiers().isEmpty()) {
+ if (!filter.getResourceQualifiers().isEmpty()) {
sql.append(" AND rindex.qualifier IN ");
- appendInStatement(filter.resourceQualifiers(), sql);
+ appendInStatement(filter.getResourceQualifiers(), sql);
}
sql.append(") ");
}
} else {
Long rootSnapshotId = (baseSnapshot.getRootId() != null ? baseSnapshot.getRootId() : baseSnapshot.getId());
sql.append(" AND s.root_snapshot_id=").append(rootSnapshotId);
- sql.append(" AND s.path LIKE '").append(baseSnapshot.getPath()).append(baseSnapshot.getId()).append(".%'");
+ sql.append(" AND s.path LIKE '").append(StringUtils.defaultString(baseSnapshot.getPath())).append(baseSnapshot.getId()).append(".%'");
}
}
}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.core.measure;
-
-import org.sonar.api.measures.Metric;
-
-public class MeasureFilterValueCondition {
-
- public static enum Operator {
- GREATER(">"), GREATER_OR_EQUALS(">="), EQUALS("="), LESS("<"), LESS_OR_EQUALS("<=");
-
- private String sql;
-
- private Operator(String sql) {
- this.sql = sql;
- }
-
- public String getSql() {
- return sql;
- }
- }
-
- private final Metric metric;
- private final Operator operator;
- private final float value;
- private int period = -1;
-
- public MeasureFilterValueCondition(Metric metric, Operator operator, float value) {
- this.metric = metric;
- this.operator = operator;
- this.value = value;
- }
-
- public MeasureFilterValueCondition setPeriod(int period) {
- this.period = (period > 0 ? period : -1);
- return this;
- }
-
- public Metric metric() {
- return metric;
- }
-
- public Operator operator() {
- return operator;
- }
-
- public double value() {
- return value;
- }
-
- public int period() {
- return period;
- }
-
- String valueColumn() {
- if (period > 0) {
- return "pm.variation_value_" + period;
- }
- return "pm.value";
- }
-
- void appendSql(StringBuilder sql) {
- sql.append(" pm.metric_id=");
- sql.append(metric.getId());
- sql.append(" AND ").append(valueColumn()).append(operator.getSql()).append(value);
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.core.measure;
-
-import org.sonar.core.resource.SnapshotDto;
-
-public class MesasureFilterContext {
- private Long userId;
- private SnapshotDto baseSnapshot;
-
- public Long getUserId() {
- return userId;
- }
-
- public void setUserId(Long userId) {
- this.userId = userId;
- }
-
- public SnapshotDto getBaseSnapshot() {
- return baseSnapshot;
- }
-
- public void setBaseSnapshot(SnapshotDto baseSnapshot) {
- this.baseSnapshot = baseSnapshot;
- }
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class MeasureFilterContextTest {
+ @Test
+ public void test_empty_toString() {
+ MeasureFilterContext context = new MeasureFilterContext();
+ assertThat(context.toString()).isNotEmpty();
+ }
+
+ @Test
+ public void test_toString() {
+ MeasureFilterContext context = new MeasureFilterContext();
+ context.setJson("{}");
+ context.setSql("SELECT *");
+ context.setUserId(50L);
+ assertThat(context.toString()).isEqualTo("MeasureFilterContext[json={},sql=SELECT *,user=50]");
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import org.json.simple.parser.ParseException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.MetricFinder;
+
+import java.util.Date;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MeasureFilterDecoderTest {
+
+ private MetricFinder metricFinder;
+
+ @Before
+ public void before() {
+ metricFinder = mock(MetricFinder.class);
+ when(metricFinder.findByKey(anyString())).thenAnswer(new Answer<Metric>() {
+ public Metric answer(InvocationOnMock invocationOnMock) throws Throwable {
+ return new Metric((String) invocationOnMock.getArguments()[0]);
+ }
+ });
+ }
+
+ @Test
+ public void should_decode() throws ParseException {
+ String json = "{\"base\": \"org.struts\", \"onBaseChildren\": true, \"scopes\": [\"PRJ\"], " +
+ "\"qualifiers\": [\"TRK\",\"CLA\"], " +
+ "\"languages\": [\"java\", \"php\"], \"name\": \"Struts\", \"fromDate\": \"2012-12-25\", " +
+ "\"toDate\": \"2013-01-31\", " +
+ "\"favourites\": true, " +
+ "\"sortAsc\": true, \"sortField\": \"METRIC\", \"sortMetric\": \"ncloc\", \"sortPeriod\":5, " +
+ "\"conditions\":[{\"metric\":\"lines\", \"op\":\">\", \"val\":123.0}]}";
+
+ MeasureFilter filter = new MeasureFilterDecoder(metricFinder).decode(json);
+
+ assertThat(filter.getBaseResourceKey()).isEqualTo("org.struts");
+ assertThat(filter.isOnBaseResourceChildren()).isTrue();
+ assertThat(filter.getResourceScopes()).containsExactly("PRJ");
+ assertThat(filter.getResourceQualifiers()).containsExactly("TRK", "CLA");
+ assertThat(filter.getResourceLanguages()).containsExactly("java", "php");
+ assertThat(filter.getResourceName()).isEqualTo("Struts");
+ assertThat(filter.getFromDate().getYear()).isEqualTo(2012 - 1900);
+ assertThat(filter.getToDate().getYear()).isEqualTo(2013 - 1900);
+ assertThat(filter.isOnFavourites()).isTrue();
+ assertThat(filter.sort().metric().getKey()).isEqualTo("ncloc");
+ assertThat(filter.sort().isAsc()).isTrue();
+ MeasureFilterCondition condition = filter.getMeasureConditions().get(0);
+ assertThat(condition.metric().getKey()).isEqualTo("lines");
+ assertThat(condition.operator()).isEqualTo(">");
+ assertThat(condition.value()).isEqualTo(123.0);
+ }
+
+ @Test
+ public void should_set_max_date_by_number_of_days() throws ParseException {
+ String json = "{\"beforeDays\": 5}";
+
+ MeasureFilter filter = new MeasureFilterDecoder(metricFinder).decode(json);
+
+ assertThat(filter.getFromDate()).isNull();
+ assertThat(filter.getToDate().before(new Date())).isTrue();
+ }
+
+ @Test
+ public void should_set_min_date_by_number_of_days() throws ParseException {
+ String json = "{\"afterDays\": 5}";
+
+ MeasureFilter filter = new MeasureFilterDecoder(metricFinder).decode(json);
+
+ assertThat(filter.getToDate()).isNull();
+ assertThat(filter.getFromDate().before(new Date())).isTrue();
+ }
+
+ @Test
+ public void test_default_values() throws ParseException {
+ MeasureFilter filter = new MeasureFilterDecoder(metricFinder).decode("{}");
+
+ assertThat(filter.getBaseResourceKey()).isNull();
+ assertThat(filter.isOnBaseResourceChildren()).isFalse();
+ assertThat(filter.getResourceScopes()).isEmpty();
+ assertThat(filter.getResourceQualifiers()).isEmpty();
+ assertThat(filter.getResourceLanguages()).isEmpty();
+ assertThat(filter.getResourceName()).isNull();
+ assertThat(filter.getFromDate()).isNull();
+ assertThat(filter.getToDate()).isNull();
+ assertThat(filter.isOnFavourites()).isFalse();
+ assertThat(filter.sort().metric()).isNull();
+ assertThat(filter.sort().getPeriod()).isNull();
+ assertThat(filter.sort().onMeasures()).isFalse();
+ assertThat(filter.sort().field()).isEqualTo(MeasureFilterSort.Field.NAME);
+ assertThat(filter.sort().isAsc()).isTrue();
+ assertThat(filter.getMeasureConditions()).isEmpty();
+
+ }
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.measure;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.junit.Test;
+import org.slf4j.Logger;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class MeasureFilterEngineTest {
+ @Test
+ public void should_decode_json_and_execute_filter() throws Exception {
+ MeasureFilterDecoder decoder = mock(MeasureFilterDecoder.class);
+ MeasureFilter filter = new MeasureFilter();
+ when(decoder.decode("{}")).thenReturn(filter);
+ MeasureFilterExecutor executor = mock(MeasureFilterExecutor.class);
+ Logger logger = mock(Logger.class);
+ when(logger.isDebugEnabled()).thenReturn(true);
+
+ MeasureFilterEngine engine = new MeasureFilterEngine(decoder, executor);
+
+ final long userId = 50L;
+ engine.execute("{}", userId, logger);
+ verify(executor).execute(refEq(filter), argThat(new BaseMatcher<MeasureFilterContext>() {
+ public boolean matches(Object o) {
+ MeasureFilterContext context = (MeasureFilterContext) o;
+ return "{}".equals(context.getJson()) && context.getUserId() == userId;
+ }
+
+ public void describeTo(Description description) {
+ }
+ }));
+ verify(logger).debug(anyString());
+ }
+}
import org.sonar.core.resource.ResourceDao;
import org.sonar.core.resource.SnapshotDto;
+import java.sql.SQLException;
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
}
@Test
- public void invalid_filter_should_not_return_results() {
- MeasureFilter filter = new MeasureFilter();
- // no qualifiers
- assertThat(executor.execute(filter, null)).isEmpty();
+ public void invalid_filter_should_not_return_results() throws SQLException {
+ MeasureFilter filter = new MeasureFilter().setUserFavourites(true);
+ // anonymous user does not have favourites
+ assertThat(executor.execute(filter, new MeasureFilterContext())).isEmpty();
}
@Test
public void filter_is_not_valid_if_missing_base_snapshot() {
- MesasureFilterContext context = new MesasureFilterContext();
+ MeasureFilterContext context = new MeasureFilterContext();
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setOnBaseResourceChildren(true);
assertThat(MeasureFilterExecutor.isValid(filter, context)).isFalse();
assertThat(MeasureFilterExecutor.isValid(filter, context)).isTrue();
}
+ @Test
+ public void filter_is_not_valid_if_condition_on_unknown_metric() {
+ MeasureFilterContext context = new MeasureFilterContext();
+ MeasureFilter filter = new MeasureFilter().addCondition(new MeasureFilterCondition(null, "<", 3.0));
+ assertThat(MeasureFilterExecutor.isValid(filter, context)).isFalse();
+ }
+
+ @Test
+ public void filter_is_not_valid_if_sorting_on_unknown_metric() {
+ MeasureFilterContext context = new MeasureFilterContext();
+ MeasureFilter filter = new MeasureFilter().setSortOnMetric(null);
+ assertThat(MeasureFilterExecutor.isValid(filter, context)).isFalse();
+ }
+
@Test
public void filter_is_not_valid_if_anonymous_favourites() {
- MesasureFilterContext context = new MesasureFilterContext();
+ MeasureFilterContext context = new MeasureFilterContext();
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setUserFavourites(true);
assertThat(MeasureFilterExecutor.isValid(filter, context)).isFalse();
}
@Test
- public void projects_without_measure_conditions() {
+ public void projects_without_measure_conditions() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setSortOn(MeasureFilterSort.Field.LANGUAGE);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);
verifyJavaProject(rows.get(0));
}
@Test
- public void sort_by_ascending_resource_name() {
+ public void sort_by_ascending_resource_name() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setSortAsc(true);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// Big -> Tiny
assertThat(rows).hasSize(2);
}
@Test
- public void sort_by_descending_resource_name() {
+ public void sort_by_descending_resource_name() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setSortAsc(false);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// Tiny -> Big
assertThat(rows).hasSize(2);
}
@Test
- public void sort_by_ascending_text_measure() {
+ public void sort_by_ascending_text_measure() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setSortOnMetric(METRIC_PROFILE);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);
verifyPhpProject(rows.get(0));//php way
}
@Test
- public void sort_by_descending_text_measure() {
+ public void sort_by_descending_text_measure() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setSortOnMetric(METRIC_PROFILE).setSortAsc(false);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);
verifyJavaProject(rows.get(0));// Sonar way
}
@Test
- public void sort_by_missing_text_measure() {
+ public void sort_by_missing_text_measure() throws SQLException {
// the metric 'profile' is not set on files
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setSortOnMetric(METRIC_PROFILE);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);//2 files randomly sorted
}
@Test
- public void sort_by_ascending_numeric_measure() {
+ public void sort_by_ascending_numeric_measure() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setSortOnMetric(METRIC_LINES);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// Tiny -> Big
assertThat(rows).hasSize(2);
}
@Test
- public void sort_by_descending_numeric_measure() {
+ public void sort_by_descending_numeric_measure() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setSortOnMetric(METRIC_LINES).setSortAsc(false);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// Big -> Tiny
assertThat(rows).hasSize(2);
}
@Test
- public void sort_by_missing_numeric_measure() {
+ public void sort_by_missing_numeric_measure() throws SQLException {
// coverage measures are not computed
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setSortOnMetric(METRIC_COVERAGE);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// 2 files, random order
assertThat(rows).hasSize(2);
}
@Test
- public void sort_by_ascending_variation() {
+ public void sort_by_ascending_variation() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setSortOnMetric(METRIC_LINES).setSortOnPeriod(5);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);
verifyJavaProject(rows.get(0));// +400
}
@Test
- public void sort_by_descending_variation() {
+ public void sort_by_descending_variation() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK")
.setSortOnMetric(METRIC_LINES).setSortOnPeriod(5).setSortAsc(false);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);
verifyPhpProject(rows.get(0));// +4900
}
@Test
- public void sort_by_ascending_date() {
+ public void sort_by_ascending_date() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setSortOn(MeasureFilterSort.Field.DATE);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
verifyJavaProject(rows.get(0));// 2008
verifyPhpProject(rows.get(1));// 2012
}
@Test
- public void sort_by_descending_date() {
+ public void sort_by_descending_date() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setSortOn(MeasureFilterSort.Field.DATE).setSortAsc(false);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
verifyPhpProject(rows.get(0));// 2012
verifyJavaProject(rows.get(1));// 2008
}
@Test
- public void condition_on_numeric_measure() {
+ public void condition_on_numeric_measure() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA")
.setSortOnMetric(METRIC_LINES)
- .addCondition(new MeasureFilterValueCondition(METRIC_LINES, MeasureFilterValueCondition.Operator.GREATER, 200));
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ .addCondition(new MeasureFilterCondition(METRIC_LINES, ">", 200));
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(1);
verifyJavaBigFile(rows.get(0));
}
@Test
- public void condition_on_measure_variation() {
+ public void condition_on_measure_variation() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK")
.setSortOnMetric(METRIC_LINES)
- .addCondition(new MeasureFilterValueCondition(METRIC_LINES, MeasureFilterValueCondition.Operator.GREATER, 1000).setPeriod(5));
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ .addCondition(new MeasureFilterCondition(METRIC_LINES, ">", 1000).setPeriod(5));
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(1);
verifyPhpProject(rows.get(0));
}
@Test
- public void multiple_conditions_on_numeric_measures() {
+ public void multiple_conditions_on_numeric_measures() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA")
.setSortOnMetric(METRIC_LINES)
- .addCondition(new MeasureFilterValueCondition(METRIC_LINES, MeasureFilterValueCondition.Operator.GREATER, 2))
- .addCondition(new MeasureFilterValueCondition(METRIC_LINES, MeasureFilterValueCondition.Operator.LESS_OR_EQUALS, 50));
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ .addCondition(new MeasureFilterCondition(METRIC_LINES, ">", 2))
+ .addCondition(new MeasureFilterCondition(METRIC_LINES, "<=", 50));
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(1);
verifyJavaTinyFile(rows.get(0));
}
@Test
- public void filter_by_language() {
+ public void filter_by_language() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setResourceLanguages("java", "cobol");
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(1);
verifyJavaProject(rows.get(0));
}
@Test
- public void filter_by_min_date() {
+ public void filter_by_min_date() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setFromDate(DateUtils.parseDate("2012-12-13"));
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// php has been analyzed in 2012-12-13, whereas java project has been analyzed in 2008
assertThat(rows).hasSize(1);
}
@Test
- public void filter_by_range_of_dates() {
+ public void filter_by_range_of_dates() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK")
.setFromDate(DateUtils.parseDate("2007-01-01"))
.setToDate(DateUtils.parseDate("2010-01-01"));
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
// php has been analyzed in 2012-12-13, whereas java project has been analyzed in 2008
assertThat(rows).hasSize(1);
}
@Test
- public void filter_by_resource_name() {
+ public void filter_by_resource_name() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK").setResourceName("PHP Proj");
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(1);
verifyPhpProject(rows.get(0));
}
@Test
- public void filter_by_base_resource() {
+ public void filter_by_base_resource() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("CLA").setBaseResourceKey("java_project");
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(2);
// default sort is on resource name
}
@Test
- public void filter_by_parent_resource() {
- MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK", "PAC", "CLA").setBaseResourceKey("java_project").setOnBaseResourceChildren(true);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ public void filter_by_parent_resource() throws SQLException {
+ MeasureFilter filter = new MeasureFilter().setBaseResourceKey("java_project").setOnBaseResourceChildren(true);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).hasSize(1);// the package org.sonar.foo
assertThat(rows.get(0).getSnapshotId()).isEqualTo(JAVA_PACKAGE_SNAPSHOT_ID);
}
@Test
- public void filter_by_parent_without_children() {
+ public void filter_by_parent_without_children() throws SQLException {
MeasureFilter filter = new MeasureFilter().setResourceQualifiers("TRK", "PAC", "CLA").setBaseResourceKey("java_project:org.sonar.foo.Big").setOnBaseResourceChildren(true);
- List<MeasureFilterRow> rows = executor.execute(filter, null);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
assertThat(rows).isEmpty();
}
@Test
- public void filter_by_user_favourites() {
+ public void filter_by_user_favourites() throws SQLException {
MeasureFilter filter = new MeasureFilter().setUserFavourites(true);
- List<MeasureFilterRow> rows = executor.execute(filter, 50L);
+ List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext().setUserId(50L));
assertThat(rows).hasSize(2);
verifyJavaBigFile(rows.get(0));
<level value="DEBUG"/>
</logger>
+ <logger name="org.sonar.MEASURE_FILTER">
+ <level value="DEBUG"/>
+ </logger>
+
<root>
<level value="INFO"/>
<appender-ref ref="STDOUT"/>
<level value="DEBUG"/>
</logger>
+ <logger name="org.sonar.MEASURE_FILTER">
+ <level value="DEBUG"/>
+ </logger>
+
<root>
<level value="INFO"/>
<appender-ref ref="STDOUT"/>
<level value="DEBUG"/>
</logger>
+ <logger name="org.sonar.MEASURE_FILTER">
+ <level value="DEBUG"/>
+ </logger>
+
<root>
<level value="INFO"/>
<appender-ref ref="STDOUT"/>
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.apache.commons.lang.time.DateUtils;
-
-import java.util.Calendar;
-import java.util.Date;
-
-public class DateCriterion {
-
- private String operator;
- private Date date;
-
- public DateCriterion(String operator, Date date) {
- this.operator = operator;
- this.date = date;
- }
-
- public DateCriterion() {
- }
-
- public String getOperator() {
- return operator;
- }
-
- public DateCriterion setOperator(String operator) {
- this.operator = operator;
- return this;
- }
-
- public Date getDate() {
- return date;
- }
-
- public DateCriterion setDate(Date date) {
- this.date = date;
- return this;
- }
-
- public DateCriterion setDate(int daysAgo) {
- this.date = DateUtils.addDays(new Date(), -daysAgo);
- this.date = DateUtils.truncate(this.date, Calendar.DATE);
- return this;
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
- .append("operator", operator)
- .append("date", date)
- .toString();
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.resources.Qualifiers;
-
-import java.util.List;
-import java.util.Set;
-
-public class Filter {
-
- // path
- private Integer rootSnapshotId;
- private Integer baseSnapshotId;
- private String baseSnapshotPath;
-
- // filters on resources
- private Set<String> scopes;
- private Set<String> qualifiers;
- private Set<String> languages;
- private Set<Integer> favouriteIds;
- private DateCriterion dateCriterion;
- private String keyRegexp;
- private String nameRegexp;
- private boolean onDirectChildren = false;
-
- // filters on measures
- private List<MeasureCriterion> measureCriteria = Lists.newLinkedList();
- private int periodIndex = 0;
-
- // sorting
- private Integer sortedMetricId;
- private Boolean sortedByMeasureVariation = Boolean.FALSE;
- private boolean sortedByLanguage;
- private boolean sortedByName;
- private boolean sortedByKey;
- private boolean sortedByDate;
- private boolean sortedByVersion;
- private boolean isNumericMetric = true;
- private boolean ascendingSort = true;
-
- public Filter setPath(Integer rootSnapshotId, Integer snapshotId, String snapshotPath) {
- this.baseSnapshotId = snapshotId;
- if (rootSnapshotId == null) {
- this.rootSnapshotId = snapshotId;
- } else {
- this.rootSnapshotId = rootSnapshotId;
- }
- this.baseSnapshotPath = StringUtils.defaultString(snapshotPath, ""); //With Oracle the path can be null (see SONAR-2582)
- return this;
- }
-
- public Integer getRootSnapshotId() {
- return rootSnapshotId;
- }
-
- public boolean hasBaseSnapshot() {
- return baseSnapshotId != null;
- }
-
- public Integer getBaseSnapshotId() {
- return baseSnapshotId;
- }
-
- public String getBaseSnapshotPath() {
- return baseSnapshotPath;
- }
-
- public Set<String> getScopes() {
- return scopes;
- }
-
- public boolean hasScopes() {
- return scopes != null && !scopes.isEmpty();
- }
-
- public Filter setScopes(Set<String> scopes) {
- this.scopes = scopes;
- return this;
- }
-
- public Filter setScopes(String... scopes) {
- this.scopes = Sets.newHashSet(scopes);
- return this;
- }
-
- public Set<String> getQualifiers() {
- return qualifiers;
- }
-
- public boolean hasQualifiers() {
- return qualifiers != null && !qualifiers.isEmpty();
- }
-
- public Filter setQualifiers(Set<String> qualifiers) {
- this.qualifiers = qualifiers;
- return this;
- }
-
- public Filter setQualifiers(String... qualifiers) {
- this.qualifiers = Sets.newHashSet(qualifiers);
- return this;
- }
-
- public Set<String> getLanguages() {
- return languages;
- }
-
- public boolean hasLanguages() {
- return languages != null && !languages.isEmpty();
- }
-
- public Filter setLanguages(Set<String> languages) {
- this.languages = languages;
- return this;
- }
-
- public Filter setLanguages(String... languages) {
- this.languages = Sets.newHashSet(languages);
- return this;
- }
-
- public Set<Integer> getFavouriteIds() {
- return favouriteIds;
- }
-
- public boolean hasFavouriteIds() {
- return favouriteIds != null && !favouriteIds.isEmpty();
- }
-
- public Filter setFavouriteIds(Set<Integer> favouriteIds) {
- this.favouriteIds = favouriteIds;
- return this;
- }
-
- public Filter setFavouriteIds(Integer... favouriteIds) {
- this.favouriteIds = Sets.newHashSet(favouriteIds);
- return this;
- }
-
- public Integer getSortedMetricId() {
- return sortedMetricId;
- }
-
- public boolean isNumericMetric() {
- return isNumericMetric;
- }
-
- public boolean isTextSort() {
- return !isNumericMetric || sortedByLanguage || sortedByName || sortedByVersion || sortedByKey;
- }
-
- public Filter setSortedMetricId(Integer id, boolean isNumericValue, Boolean isVariation) {
- unsetSorts();
- this.sortedMetricId = id;
- this.isNumericMetric = isNumericValue;
- this.sortedByMeasureVariation = isVariation;
- return this;
- }
-
- public boolean isSortedByLanguage() {
- return sortedByLanguage;
- }
-
- public Filter setSortedByLanguage() {
- unsetSorts();
- this.sortedByLanguage = true;
- return this;
- }
-
- public boolean isSortedByName() {
- return sortedByName;
- }
-
- public boolean isSortedByKey() {
- return sortedByKey;
- }
-
- public boolean isSortedByVersion() {
- return sortedByVersion;
- }
-
- public Filter setSortedByVersion() {
- unsetSorts();
- this.sortedByVersion = true;
- return this;
- }
-
- public boolean isSorted() {
- return isSortedByLanguage() || isSortedByName() || isSortedByKey() || isSortedByDate() || isSortedByVersion() || getSortedMetricId() != null;
- }
-
- public boolean isSortedByDate() {
- return sortedByDate;
- }
-
- public Filter setSortedByDate() {
- unsetSorts();
- sortedByDate = true;
- return this;
- }
-
- public Filter setSortedByName() {
- unsetSorts();
- this.sortedByName = true;
- return this;
- }
-
- public Filter setSortedByKey() {
- unsetSorts();
- this.sortedByKey = true;
- return this;
- }
-
- private void unsetSorts() {
- this.sortedByDate = false;
- this.sortedByLanguage = false;
- this.sortedByName = false;
- this.sortedByKey = false;
- this.sortedMetricId = null;
- this.sortedByVersion = false;
- this.isNumericMetric = true;
- }
-
- public List<MeasureCriterion> getMeasureCriteria() {
- return measureCriteria;
- }
-
- public Filter setMeasureCriteria(List<MeasureCriterion> l) {
- this.measureCriteria = l;
- return this;
- }
-
- public Filter addMeasureCriterion(MeasureCriterion c) {
- this.measureCriteria.add(c);
- return this;
- }
-
- public Filter createMeasureCriterionOnValue(Integer metricId, String operator, Double value, Boolean variation) {
- this.measureCriteria.add(new MeasureCriterion(metricId, operator, value, variation));
- return this;
- }
-
- public boolean hasMeasureCriteria() {
- return !measureCriteria.isEmpty();
- }
-
- protected boolean hasMeasureCriteriaOnMetric(Integer metricId) {
- if (metricId != null) {
- for (MeasureCriterion criterion : measureCriteria) {
- if (metricId.equals(criterion.getMetricId())) {
- return true;
- }
- }
- }
- return false;
- }
-
- public boolean mustJoinMeasuresTable() {
- return sortedMetricId != null || hasMeasureCriteria();
- }
-
- public boolean isAscendingSort() {
- return ascendingSort;
- }
-
- public Filter setAscendingSort(boolean b) {
- this.ascendingSort = b;
- return this;
- }
-
- public DateCriterion getDateCriterion() {
- return dateCriterion;
- }
-
- public Filter setDateCriterion(DateCriterion dc) {
- this.dateCriterion = dc;
- return this;
- }
-
- public Filter setDateCriterion(String operator, Integer daysAgo) {
- this.dateCriterion = new DateCriterion().setOperator(operator).setDate(daysAgo);
- return this;
- }
-
- public String getKeyRegexp() {
- return keyRegexp;
- }
-
- public Filter setKeyRegexp(String s) {
- this.keyRegexp = s;
- return this;
- }
-
- public String getNameRegexp() {
- return nameRegexp;
- }
-
- public Filter setNameRegexp(String s) {
- this.nameRegexp = s;
- return this;
- }
-
- public int getPeriodIndex() {
- return periodIndex;
- }
-
- public void setPeriodIndex(int i) {
- this.periodIndex = i;
- }
-
- public boolean isOnPeriod() {
- return periodIndex > 0;
- }
-
- public boolean isOnDirectChildren() {
- return onDirectChildren;
- }
-
- public void setOnDirectChildren(boolean b) {
- this.onDirectChildren = b;
- }
-
- static String getVariationColumn(int periodIndex) {
- switch (periodIndex) {
- case 1:
- return "variation_value_1";
- case 2:
- return "variation_value_2";
- case 3:
- return "variation_value_3";
- case 4:
- return "variation_value_4";
- case 5:
- return "variation_value_5";
- default:
- return null;
- }
- }
-
- String getColumnToSort() {
- String col = "text_value";
- if (isNumericMetric()) {
- col = (sortedByMeasureVariation == Boolean.TRUE ? getVariationColumn(periodIndex) : "value");
- }
- return col;
- }
-
- public boolean mustReturnEmptyResult() {
- boolean hasCriterionOnVariation = false;
- for (MeasureCriterion criterion : measureCriteria) {
- if (criterion.isVariation() == Boolean.TRUE) {
- hasCriterionOnVariation = true;
- }
- }
- return (hasCriterionOnVariation && !isOnPeriod());
- }
-
- @Override
- public String toString() {
- return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
- }
-
- public static Filter createForAllQualifiers() {
- return new Filter().setQualifiers(
- Qualifiers.VIEW, Qualifiers.SUBVIEW,
- Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.DIRECTORY, Qualifiers.PACKAGE,
- Qualifiers.FILE, Qualifiers.CLASS, Qualifiers.UNIT_TEST_FILE, Qualifiers.LIBRARY, Qualifiers.PARAGRAPH);
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.utils.SonarException;
-import org.sonar.api.utils.TimeProfiler;
-import org.sonar.core.persistence.Database;
-import org.sonar.core.persistence.dialect.Dialect;
-import org.sonar.core.persistence.dialect.MsSql;
-
-import javax.persistence.Query;
-
-import java.util.Collections;
-
-public class FilterExecutor implements ServerComponent {
- private static final Logger LOG = LoggerFactory.getLogger(FilterExecutor.class);
- private static final int SQL_INITIAL_SIZE = 1000;
- private DatabaseSession session;
- private Dialect dialect;
-
- public FilterExecutor(DatabaseSession session, Database database) {
- this(session, database.getDialect());
- }
-
- @VisibleForTesting
- FilterExecutor(DatabaseSession session, Dialect dialect) {
- this.session = session;
- this.dialect = dialect;
- }
-
- public FilterResult execute(Filter filter) {
- if (filter.mustReturnEmptyResult()) {
- return new FilterResult(filter, Collections.<Object[]> emptyList());
- }
-
- String sql = null;
- try {
- TimeProfiler profiler = new TimeProfiler(FilterExecutor.class).setLevelToDebug().start("Build/execute SQL query");
- sql = toSql(filter);
- LOG.debug("SQL: " + sql);
- Query query = session.getEntityManager().createNativeQuery(sql);
- setHqlParameters(filter, query);
- FilterResult result = new FilterResult(filter, query.getResultList());
- profiler.stop();
-
- profiler.start("Process rows");
- result.removeUnvalidRows();
- profiler.stop();
-
- profiler.start("Sort rows");
- result.sort();
- profiler.stop();
- return result;
-
- } catch (Exception e) {
- throw new SonarException("Fail to execute filter: " + filter.toString() + ", sql=" + sql, e);
- }
- }
-
- @VisibleForTesting
- String toSql(Filter filter) {
- StringBuilder sql = new StringBuilder(SQL_INITIAL_SIZE);
- addSelectColumns(filter, sql);
- addFromClause(filter, sql);
- addWhereClause(filter, sql);
- return sql.toString();
- }
-
- private void addSelectColumns(Filter filter, StringBuilder sql) {
- sql.append("SELECT s.id, MAX(s.project_id) as pid, MAX(s.root_project_id) as rpid");
- if (filter.isSortedByLanguage()) {
- sql.append(", MAX(p.language) as lang ");
-
- } else if (filter.isSortedByName()) {
- sql.append(", MAX(p.long_name) as name ");
-
- } else if (filter.isSortedByKey()) {
- sql.append(", MAX(p.kee) as kee ");
-
- } else if (filter.isSortedByDate()) {
- sql.append(", MAX(s.created_at) as createdat ");
-
- } else if (filter.isSortedByVersion()) {
- sql.append(", MAX(s.version) as version ");
- }
- if (filter.getSortedMetricId() != null) {
- sql.append(", MAX(CASE WHEN pm.metric_id=");
- sql.append(filter.getSortedMetricId());
- sql.append(" THEN ");
- sql.append(filter.getColumnToSort());
- sql.append(" ELSE NULL END) AS sortvalue");
- sql.append(" ");
- }
- for (int index = 0; index < filter.getMeasureCriteria().size(); index++) {
- MeasureCriterion criterion = filter.getMeasureCriteria().get(index);
- String column = (criterion.isVariation() ? Filter.getVariationColumn(filter.getPeriodIndex()) : "value");
- sql.append(", MAX(CASE WHEN pm.metric_id=");
- sql.append(criterion.getMetricId());
- sql.append(" AND pm.");
- sql.append(column);
- sql.append(criterion.getOperator());
- sql.append(criterion.getValue());
- sql.append(" THEN ");
- sql.append(column);
- sql.append(" ELSE NULL END) AS crit_");
- sql.append(index);
- sql.append(" ");
- }
- }
-
- private void addFromClause(Filter filter, StringBuilder sql) {
- sql.append(" FROM snapshots s ");
- if (filter.mustJoinMeasuresTable()) {
- sql.append(" INNER JOIN project_measures pm ");
- if (MsSql.ID.equals(dialect.getId())) {
- // SONAR-3422
- sql.append(" WITH (INDEX(measures_sid_metric)) ");
- }
- sql.append(" ON s.id=pm.snapshot_id ");
- }
- sql.append(" INNER JOIN projects p ON s.project_id=p.id ");
- }
-
- private void addWhereClause(Filter filter, StringBuilder sql) {
- sql.append(" WHERE ");
- if (filter.mustJoinMeasuresTable()) {
- if (filter.hasMeasureCriteria()) {
- sql.append(" ( ");
- int index = 0;
- while (index < filter.getMeasureCriteria().size()) {
- if (index > 0) {
- sql.append(" OR ");
- }
- MeasureCriterion criterion = filter.getMeasureCriteria().get(index);
- String column = (criterion.isVariation() ? Filter.getVariationColumn(filter.getPeriodIndex()) : "value");
- sql.append("(pm.metric_id=").append(criterion.getMetricId()).append(" and pm.").append(column)
- .append(criterion.getOperator()).append(criterion.getValue()).append(")");
- index++;
- }
-
- if (filter.getSortedMetricId() != null && !filter.hasMeasureCriteriaOnMetric(filter.getSortedMetricId())) {
- sql.append(" OR (pm.metric_id=").append(filter.getSortedMetricId()).append(") ");
- }
-
- sql.append(" ) AND ");
- }
- sql.append(" pm.rule_id IS NULL AND pm.rule_priority IS NULL");
- sql.append(" AND pm.characteristic_id IS NULL");
- sql.append(" AND pm.person_id IS NULL");
- sql.append(" AND ");
- }
- sql.append(" s.status=:status AND s.islast=:islast ");
- if (filter.getScopes() != null) {
- sql.append(filter.getScopes().isEmpty() ? " AND s.scope IS NULL " : " AND s.scope IN (:scopes) ");
- }
- if (filter.hasQualifiers()) {
- sql.append(" AND s.qualifier IN (:qualifiers) ");
- } else if (!filter.isOnDirectChildren()) {
- // no criteria -> we should not display all rows but no rows
- sql.append(" AND s.qualifier IS NULL ");
- }
- if (filter.hasLanguages()) {
- sql.append(" AND p.language IN (:languages) ");
- }
- if (filter.getFavouriteIds() != null) {
- sql.append(filter.getFavouriteIds().isEmpty() ? " AND s.project_id IS NULL " : " AND s.project_id IN (:favourites) ");
- }
- if (filter.hasBaseSnapshot()) {
- if (filter.isOnDirectChildren()) {
- sql.append(" AND s.parent_snapshot_id=:parent_sid ");
- } else {
- sql.append(" AND s.root_snapshot_id=:root_sid AND s.path LIKE :path ");
- }
- }
- if (filter.getDateCriterion() != null) {
- sql.append(" AND s.created_at");
- sql.append(filter.getDateCriterion().getOperator());
- sql.append(" :date ");
- }
- if (StringUtils.isNotBlank(filter.getKeyRegexp())) {
- sql.append(" AND UPPER(p.kee) LIKE :kee");
- }
- if (StringUtils.isNotBlank(filter.getNameRegexp())) {
- sql.append(" AND UPPER(p.long_name) LIKE :name");
- }
- if (!filter.hasBaseSnapshot()) {
- sql.append(" AND p.copy_resource_id IS NULL ");
- }
- sql.append(" GROUP BY s.id");
- }
-
- private void setHqlParameters(Filter filter, Query query) {
- query.setParameter("status", Snapshot.STATUS_PROCESSED);
- query.setParameter("islast", true);
- if (filter.hasScopes()) {
- query.setParameter("scopes", filter.getScopes());
- }
- if (filter.hasQualifiers()) {
- query.setParameter("qualifiers", filter.getQualifiers());
- }
- if (filter.hasLanguages()) {
- query.setParameter("languages", filter.getLanguages());
- }
- if (filter.hasFavouriteIds()) {
- query.setParameter("favourites", filter.getFavouriteIds());
- }
- if (filter.getDateCriterion() != null) {
- query.setParameter("date", filter.getDateCriterion().getDate());
- }
- if (filter.hasBaseSnapshot()) {
- if (filter.isOnDirectChildren()) {
- query.setParameter("parent_sid", filter.getBaseSnapshotId());
- } else {
- query.setParameter("root_sid", filter.getRootSnapshotId());
- query.setParameter("path", new StringBuilder().append(
- filter.getBaseSnapshotPath()).append(filter.getBaseSnapshotId()).append(".%").toString());
- }
- }
- if (StringUtils.isNotBlank(filter.getKeyRegexp())) {
- query.setParameter("kee", StringUtils.upperCase(StringUtils.replaceChars(filter.getKeyRegexp(), '*', '%')));
- }
- if (StringUtils.isNotBlank(filter.getNameRegexp())) {
- query.setParameter("name", StringUtils.upperCase(StringUtils.replaceChars(filter.getNameRegexp(), '*', '%')));
- }
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import com.google.common.collect.Ordering;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-
-public class FilterResult {
- private List<Object[]> rows;
- private Filter filter;
- public static final int SORTED_COLUMN_INDEX = 3;
-
- public FilterResult(Filter filter, List<Object[]> rows) {
- this.rows = new ArrayList<Object[]>(rows);
- this.filter = filter;
- }
-
- /**
- * @return a list of arrays
- */
- public List<Object[]> getRows() {
- return rows;
- }
-
- public int size() {
- return rows.size();
- }
-
- public Integer getSnapshotId(Object[] row) {
- return (Integer) row[getSnapshotIdIndex()];
- }
-
- public Integer getProjectId(Object[] row) {
- return (Integer) row[getProjectIdIndex()];
- }
-
- public Integer getRootProjectId(Object[] row) {
- return (Integer) row[getRootProjectIdIndex()];
- }
-
- public int getSnapshotIdIndex() {
- return 0;
- }
-
- public int getProjectIdIndex() {
- return 1;
- }
-
- public int getRootProjectIdIndex() {
- return 2;
- }
-
- public void sort() {
- if (filter.isSorted()) {
- Comparator<Object[]> comparator = (filter.isTextSort() ? new StringIgnoreCaseComparator(SORTED_COLUMN_INDEX) : new NumericComparator(SORTED_COLUMN_INDEX));
- if (!filter.isAscendingSort()) {
- comparator = Ordering.from(comparator).reverse();
- }
- Collections.sort(rows, comparator);
- }
- }
-
- public void removeUnvalidRows() {
- int numberOfCriteria = filter.getMeasureCriteria().size();
- if (numberOfCriteria > 0) {
- int fromColumnIndex = (filter.isSorted() ? SORTED_COLUMN_INDEX + 1 : SORTED_COLUMN_INDEX);
- for (Iterator<Object[]> it = rows.iterator(); it.hasNext(); ) {
- Object[] row = it.next();
- boolean remove = false;
- for (int index = 0; index < numberOfCriteria; index++) {
- if (row[fromColumnIndex + index] == null) {
- remove = true;
- }
- }
- if (remove) {
- it.remove();
- }
- }
- }
- }
-
- static final class NumericComparator implements Comparator<Object[]>, Serializable {
- private static final long serialVersionUID = 4627704879575964978L;
- private int index;
-
- NumericComparator(int index) {
- this.index = index;
- }
-
- public int compare(Object[] a1, Object[] a2) {
- Comparable c1 = (Comparable) a1[index];
- Comparable o2 = (Comparable) a2[index];
-
- return (c1 == null ? -1 : (o2 == null ? 1 : c1.compareTo(o2)));
- }
- }
-
- static final class StringIgnoreCaseComparator implements Comparator<Object[]>, Serializable {
- private static final long serialVersionUID = 963926659201833101L;
- private int index;
-
- StringIgnoreCaseComparator(int index) {
- this.index = index;
- }
-
- public int compare(Object[] o1, Object[] o2) {
- String s1 = (String) o1[index];
- if (s1 == null) {
- return -1;
- }
- String s2 = (String) o2[index];
- if (s2 == null) {
- return 1;
- }
- return s1.compareToIgnoreCase(s2);
- }
- }
-}
-
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-
-public class MeasureCriterion {
-
- private Integer metricId;
- private String operator;
- private Double value;
- private Boolean variation;
-
- public MeasureCriterion(Integer metricId, String operator, Double value, Boolean variation) {
- this.metricId = metricId;
- this.operator = operator;
- this.value = value;
- this.variation = variation;
- }
-
- public Integer getMetricId() {
- return metricId;
- }
-
- public void setMetricId(Integer metricId) {
- this.metricId = metricId;
- }
-
- public String getOperator() {
- return operator;
- }
-
- public void setOperator(String operator) {
- this.operator = operator;
- }
-
- public Double getValue() {
- return value;
- }
-
- public void setValue(Double value) {
- this.value = value;
- }
-
- public boolean isVariation() {
- return variation==Boolean.TRUE;
- }
-
- public MeasureCriterion setVariation(Boolean b) {
- this.variation = b;
- return this;
- }
-
- @Override
- public String toString() {
- return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
- }
-}
import org.sonar.core.i18n.GwtI18n;
import org.sonar.core.i18n.I18nManager;
import org.sonar.core.i18n.RuleI18nManager;
+import org.sonar.core.measure.MeasureFilterDecoder;
+import org.sonar.core.measure.MeasureFilterEngine;
+import org.sonar.core.measure.MeasureFilterExecutor;
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseMigrator;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.DefaultDatabase;
-import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.*;
import org.sonar.core.qualitymodel.DefaultModelFinder;
import org.sonar.core.rule.DefaultRuleFinder;
import org.sonar.core.user.DefaultUserFinder;
import org.sonar.server.configuration.Backup;
import org.sonar.server.configuration.ProfilesManager;
import org.sonar.server.database.EmbeddedDatabaseFactory;
-import org.sonar.server.filters.FilterExecutor;
import org.sonar.server.notifications.NotificationService;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
-import org.sonar.server.plugins.ApplicationDeployer;
-import org.sonar.server.plugins.DefaultServerPluginRepository;
-import org.sonar.server.plugins.PluginDeployer;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerExtensionInstaller;
-import org.sonar.server.plugins.UpdateCenterClient;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
import org.sonar.server.qualitymodel.DefaultModelManager;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.server.startup.*;
-import org.sonar.server.ui.CodeColorizers;
-import org.sonar.server.ui.JRubyI18n;
-import org.sonar.server.ui.PageDecorations;
-import org.sonar.server.ui.SecurityRealmFactory;
-import org.sonar.server.ui.Views;
+import org.sonar.server.ui.*;
import javax.servlet.ServletContext;
servicesContainer.addSingleton(UpdateCenterMatrixFactory.class);
servicesContainer.addSingleton(PluginDownloader.class);
servicesContainer.addSingleton(ServerIdGenerator.class);
- servicesContainer.addComponent(FilterExecutor.class, false);
servicesContainer.addSingleton(DefaultModelFinder.class); // depends on plugins
servicesContainer.addSingleton(DefaultModelManager.class);
servicesContainer.addSingleton(Plugins.class);
servicesContainer.addSingleton(NewUserNotifier.class);
servicesContainer.addSingleton(SettingsChangeNotifier.class);
servicesContainer.addSingleton(PageDecorations.class);
+ servicesContainer.addSingleton(MeasureFilterDecoder.class);
+ servicesContainer.addSingleton(MeasureFilterExecutor.class);
+ servicesContainer.addSingleton(MeasureFilterEngine.class);
// Notifications
servicesContainer.addSingleton(EmailSettings.class);
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleRepository;
import org.sonar.api.utils.ValidationMessages;
-import org.sonar.api.web.Footer;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.api.web.RubyRailsWebservice;
-import org.sonar.api.web.Widget;
+import org.sonar.api.web.*;
import org.sonar.api.workflow.Review;
import org.sonar.api.workflow.internal.DefaultReview;
import org.sonar.api.workflow.internal.DefaultWorkflowContext;
import org.sonar.api.workflow.screen.Screen;
import org.sonar.core.i18n.RuleI18nManager;
+import org.sonar.core.measure.MeasureFilterEngine;
+import org.sonar.core.measure.MeasureFilterRow;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.DatabaseMigrator;
import org.sonar.core.purge.PurgeDao;
import org.sonar.markdown.Markdown;
import org.sonar.server.configuration.Backup;
import org.sonar.server.configuration.ProfilesManager;
-import org.sonar.server.filters.Filter;
-import org.sonar.server.filters.FilterExecutor;
-import org.sonar.server.filters.FilterResult;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
-import org.sonar.server.platform.NewUserNotifier;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.platform.ServerIdGenerator;
-import org.sonar.server.platform.ServerSettings;
-import org.sonar.server.platform.SettingsChangeNotifier;
-import org.sonar.server.plugins.DefaultServerPluginRepository;
-import org.sonar.server.plugins.PluginDeployer;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.UpdateCenterMatrix;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.platform.*;
+import org.sonar.server.plugins.*;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.updatecenter.common.Version;
import javax.annotation.Nullable;
-
import java.net.InetAddress;
import java.sql.Connection;
import java.util.Collection;
return getContainer().getComponentByType(componentType);
}
- public FilterResult executeFilter(Filter filter) {
- return get(FilterExecutor.class).execute(filter);
+ public List<MeasureFilterRow> executeMeasureFilter(String json, @Nullable Long userId) throws Exception {
+ return get(MeasureFilterEngine.class).execute(json, userId);
}
public Collection<ResourceType> getResourceTypesForFilter() {
public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) {
getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId],
- RulePriority.values()[newSeverityId], userName);
+ RulePriority.values()[newSeverityId], userName);
}
public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) {
// notifier is null when creating the administrator in the migration script 011.
if (notifier != null) {
notifier.onNewUser(NewUserHandler.Context.builder()
- .setLogin(fields.get("login"))
- .setName(fields.get("name"))
- .setEmail(fields.get("email"))
- .build());
+ .setLogin(fields.get("login"))
+ .setName(fields.get("name"))
+ .setEmail(fields.get("email"))
+ .build());
}
}
}
def on_direct_children?
if resource_id
c = criterion('direct-children')
- c && c.text_value=='true'
+ c ? c.text_value=='true' : false
else
false
end
private
- def extract_snapshot_ids(sql_rows)
+ def extract_snapshot_ids(filter_rows)
sids=[]
- project_ids=sql_rows.map{|r| r[2] ? to_integer(r[2]) : to_integer(r[1])}.compact.uniq
+ project_ids=filter_rows.map{|row| row.getResourceRootId()}.compact.uniq
authorized_pids=select_authorized(:user, project_ids)
- sql_rows.each do |row|
- pid=(row[2] ? to_integer(row[2]) : to_integer(row[1]))
- if authorized_pids.include?(pid)
- sids<<to_integer(row[0])
+ filter_rows.each do |row|
+ if authorized_pids.include?(row.getResourceRootId())
+ sids<<row.getSnapshotId()
end
end
sids
end
-
- def to_integer(obj)
- if obj.is_a?(Fixnum)
- obj
- else
- # java.math.BigDecimal
- obj.intValue()
- end
- end
end
\ No newline at end of file
def self.execute(filter, authenticated_system, options={})
filter_context = FilterContext.new(filter, options)
- java_filter=Java::OrgSonarServerFilters::Filter.new
+
+ filter_json={}
#----- FILTER ON RESOURCES
if filter.resource_id
- snapshot=Snapshot.find(:first, :conditions => {:project_id => filter.resource_id, :islast => true})
- if snapshot
- java_filter.setPath(snapshot.root_snapshot_id, snapshot.id, snapshot.path)
- else
- java_filter.setPath(-1, -1, '')
- end
+ filter_json[:base]=filter.resource.key
end
if filter.favourites
- java_filter.setFavouriteIds((authenticated_system.current_user.favourite_ids||[]).to_java(:Integer))
+ filter_json[:favourites]=true
end
date_criterion=filter.criterion('date')
if date_criterion
- java_filter.setDateCriterion(date_criterion.operator, date_criterion.value.to_i)
+ if date_criterion.operator=='<'
+ filter_json[:beforeDays]=date_criterion.value.to_i
+ else
+ filter_json[:afterDays]=date_criterion.value.to_i
+ end
end
key_criterion=filter.criterion('key')
if key_criterion
- java_filter.setKeyRegexp(key_criterion.text_value)
+ #java_filter.setKeyRegexp(key_criterion.text_value)
end
name_criterion=filter.criterion('name')
if name_criterion
- java_filter.setNameRegexp(name_criterion.text_value)
+ filter_json[:name]=name_criterion.text_value
end
qualifier_criterion=filter.criterion('qualifier')
if qualifier_criterion
- java_filter.setQualifiers(qualifier_criterion.text_values.to_java(:String))
- else
- java_filter.setQualifiers([].to_java(:String))
+ filter_json[:qualifiers]=qualifier_criterion.text_values
end
- java_filter.setOnDirectChildren(filter.on_direct_children?)
+ filter_json[:onBaseChildren]=filter.on_direct_children?
language_criterion=filter.criterion('language')
if language_criterion
- java_filter.setLanguages(language_criterion.text_values.to_java :String)
+ filter_json[:languages]=language_criterion.text_values
end
#----- FILTER ON MEASURES
- filter.measure_criteria.each do |c|
- java_filter.createMeasureCriterionOnValue(c.metric.id, c.operator, c.value, c.variation)
+ filter_json[:conditions]=filter.measure_criteria.map do |c|
+ hash = {:metric => c.metric.key, :op => c.operator, :val => c.value}
+ if c.variation
+ hash[:period] = filter_context.period_index || -1
+ end
+ hash
end
#----- SORTED COLUMN
-
if filter_context.sorted_column_id
filter.sorted_column=filter_context.sorted_column_id
end
if filter.sorted_column
- if filter.sorted_column.on_name?
- java_filter.setSortedByName()
-
- elsif filter.sorted_column.on_date?
- java_filter.setSortedByDate()
-
- elsif filter.sorted_column.on_version?
- java_filter.setSortedByVersion()
-
- elsif filter.sorted_column.on_language?
- java_filter.setSortedByLanguage()
-
- elsif filter.sorted_column.on_key?
- java_filter.setSortedByKey()
-
- elsif filter.sorted_column.on_metric? && filter.sorted_column.metric
- metric=filter.sorted_column.metric
- java_filter.setSortedMetricId(metric.id, metric.numeric?, filter.sorted_column.variation)
+ filter_json[:sortField]=filter.sorted_column.family.upcase
+ if filter.sorted_column.on_metric? && filter.sorted_column.metric
+ filter_json[:sortMetric]=filter.sorted_column.metric.key
+ if filter.sorted_column.variation
+ filter_json[:sortPeriod]=filter_context.period_index || -1
+ end
end
end
#----- SORTING DIRECTION
if filter.sorted_column
if filter_context.ascending_sort.nil?
- java_filter.setAscendingSort(filter.sorted_column.ascending?)
+ filter_json[:sortAsc]=filter.sorted_column.ascending?
else
filter.sorted_column.ascending=filter_context.ascending_sort
- java_filter.setAscendingSort(filter.sorted_column.ascending?)
+ filter_json[:sortAsc]=filter.sorted_column.ascending?
end
if filter_context.ascending_sort
filter.sorted_column.ascending=filter_context.ascending_sort
end
- java_filter.setAscendingSort(filter.sorted_column.ascending?)
+ filter_json[:sortAsc]=filter.sorted_column.ascending?
end
- #----- VARIATION
- java_filter.setPeriodIndex(filter_context.period_index)
-
#----- EXECUTION
- java_result=Java::OrgSonarServerUi::JRubyFacade.getInstance().execute_filter(java_filter)
- snapshot_ids=extract_snapshot_ids(java_result.getRows(), authenticated_system)
+ user=authenticated_system.current_user
+ rows=Api::Utils.java_facade.executeMeasureFilter(filter_json.to_json, user ? user.id : nil)
+ snapshot_ids=extract_snapshot_ids(rows, authenticated_system)
- has_security_exclusions=(snapshot_ids.size < java_result.size())
+ has_security_exclusions=(snapshot_ids.size < rows.size)
filter_context.process_results(snapshot_ids, has_security_exclusions)
filter_context
end
private
- def self.extract_snapshot_ids(sql_rows, authenticated_system)
+ def self.extract_snapshot_ids(rows, authenticated_system)
sids=[]
- project_ids=sql_rows.map { |r| r[2] ? to_integer(r[2]) : to_integer(r[1]) }.compact.uniq
+ project_ids=rows.map { |row| row.getResourceRootId() }.compact.uniq
authorized_pids=authenticated_system.select_authorized(:user, project_ids)
- sql_rows.each do |row|
- pid=(row[2] ? to_integer(row[2]) : to_integer(row[1]))
- if authorized_pids.include?(pid)
- sids<<to_integer(row[0])
+ rows.each do |row|
+ if authorized_pids.include?(row.getResourceRootId())
+ sids<<row.getSnapshotId()
end
end
sids
end
-
- def self.to_integer(obj)
- if obj.is_a?(Fixnum)
- obj
- else
- # java.math.BigDecimal
- obj.intValue()
- end
- end
end
\ No newline at end of file
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import org.apache.commons.lang.time.DateUtils;
-import org.junit.Test;
-
-import java.util.Date;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-public class DateCriterionTest {
- @Test
- public void ignoreTime() {
- DateCriterion criterion = new DateCriterion().setDate(3);
- Date date = criterion.getDate();
- assertThat(date.getHours(), is(0));
- assertThat(date.getMinutes(), is(0));
- }
-
- @Test
- public void testDaysAgo() {
- DateCriterion criterion = new DateCriterion().setDate(3);
- Date date = criterion.getDate();
- assertThat(date.getMinutes(), is(0));
- assertThat(date.getHours(), is(0));
- assertThat(DateUtils.isSameDay(date, DateUtils.addDays(new Date(), -3)), is(true));
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import com.google.common.collect.Sets;
-import org.junit.Test;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.core.persistence.dialect.H2;
-import org.sonar.core.persistence.dialect.MsSql;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.fest.assertions.Fail.fail;
-
-public class FilterExecutorTest extends AbstractDbUnitTestCase {
-
- @Test
- public void mustDefineAtLeastOneQualifier() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(new Filter());
- assertThat(result.size()).isEqualTo(0);// no qualifiers
- }
-
- @Test
- public void filterOnScopes() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setScopes(Sets.newHashSet(Resource.SCOPE_SPACE)));
- assertSnapshotIds(result, 4);
- }
-
- @Test
- public void filterOnQualifiers() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(new Filter().setQualifiers(Sets.newHashSet(Resource.QUALIFIER_PROJECT, Resource.QUALIFIER_MODULE)));
- assertSnapshotIds(result, 2, 3);
- }
-
- @Test
- public void filterOnLanguages() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setLanguages(Sets.newHashSet("java")));
- assertSnapshotIds(result, 2, 4);
- }
-
- @Test
- public void filterOnDate() throws ParseException {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2008-12-26 00:00");
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setDateCriterion(new DateCriterion(">", date)));
- assertSnapshotIds(result, 3);
- }
-
- @Test
- public void filterOnDateIncludesTime() throws ParseException {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2008-12-25 03:00");
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setDateCriterion(new DateCriterion("<", date)));
- assertSnapshotIds(result, 2, 4);
- }
-
- @Test
- public void filterOnBaseSnapshot() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setPath(2, 2, ""));
- assertSnapshotIds(result, 4);
- }
-
- @Test
- public void sortByName() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByName());
- assertSortedSnapshotIds(result, 2, 4, 3);
- }
-
- @Test
- public void sortByKey() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByKey());
- assertSortedSnapshotIds(result, 3, 2, 4);
- }
-
- @Test
- public void sortByDate() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByDate());
- assertSortedSnapshotIds(result, 2, 4, 3);
- }
-
- @Test
- public void sortByDescendingDate() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByDate().setAscendingSort(false));
- assertSortedSnapshotIds(result, 3, 4, 2);
- }
-
- @Test
- public void sortByAscendingDate() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setSortedByDate().setAscendingSort(true));
- assertSortedSnapshotIds(result, 2, 4, 3);
- }
-
- @Test
- public void sortByAscendingMeasureValue() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .setSortedMetricId(2, true, false);
-
- FilterResult result = executor.execute(filter);
- assertSortedSnapshotIds(result, 6, 5);
- }
-
- @Test
- public void sortByDecendingMeasureValue() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .setSortedMetricId(2, true, false)
- .setAscendingSort(false);
-
- FilterResult result = executor.execute(filter);
- assertSortedSnapshotIds(result, 5, 6);
- }
-
- @Test
- public void applySingleMeasureCriterion() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false));
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 5);
- }
-
- @Test
- public void applyManyMeasureCriteria() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false))
- .addMeasureCriterion(new MeasureCriterion(1, ">", 100.0, false));
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 5);
- }
-
- @Test
- public void criteriaAreExclusive() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(2, ">", 50.0, false))
- .addMeasureCriterion(new MeasureCriterion(1, "<", 100.0, false));
-
- FilterResult result = executor.execute(filter);
- assertThat(result.size()).isEqualTo(0);
- }
-
- @Test
- public void sortAndFilterMeasures() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(2, ">", 5.0, false))
- .addMeasureCriterion(new MeasureCriterion(1, ">", 5.0, false))
- .setSortedMetricId(2, true, false); // sort by coverage
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 6, 5);
- }
-
- @Test
- public void sortDescendingAndFilterMeasures() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(2, ">", 5.0, false)) // filter on coverage
- .addMeasureCriterion(new MeasureCriterion(1, ">", 5.0, false)) // filter on lines
- .setSortedMetricId(2, true, false) // sort by coverage
- .setAscendingSort(false);
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 5, 6);
- }
-
- @Test
- public void filterByResourceKey() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setKeyRegexp("*:org.sonar.*"));
- assertSnapshotIds(result, 4);
- }
-
- @Test
- public void filterByResourceKeyIsCaseInsensitive() {
- setupData("shared");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- FilterResult result = executor.execute(Filter.createForAllQualifiers().setKeyRegexp("*:ORG.SonAR.*"));
- assertSnapshotIds(result, 4);
- }
-
- @Test
- public void filterByMissingMeasureValue() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(3, ">", 0.0, false)); // filter on duplicated lines
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 6);
- }
-
- @Test
- public void filterByMissingMeasureValues() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(1, ">", 0.0, false)) // filter on lines
- .addMeasureCriterion(new MeasureCriterion(3, ">", 0.0, false)); // filter on duplicated lines
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 6);
- }
-
- @Test
- public void sortByMissingMeasureValue() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .setSortedMetricId(3, true, false); // sort by duplicated lines
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 5, 6);
- }
-
- @Test
- public void filterByMeasureValueAndSortOnOtherMetric() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(1, ">", 0.0, false)) // lines > 0
- .setSortedMetricId(2, true, false); // sort by coverage
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 6, 5);
- }
-
- @Test
- public void intersectionOfCriteriaOnSameMetric() {
- setupData("shared", "measures");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.CLASS))
- .addMeasureCriterion(new MeasureCriterion(1, ">", 400.0, false)) // lines > 400
- .addMeasureCriterion(new MeasureCriterion(1, "<", 600.0, false)); // lines > 400
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 5);
- }
-
- @Test
- public void ignoreProjectCopiesOfViews() {
- setupData("views");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setQualifiers(Sets.newHashSet(Qualifiers.PROJECT));
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 1); // the "project copy" with id 4 is ignored
- }
-
- @Test
- public void loadProjectCopiesIfPathIsAView() {
- setupData("views");
- FilterExecutor executor = new FilterExecutor(getSession(), new H2());
- Filter filter = new Filter()
- .setPath(2, 2, "")
- .setQualifiers(Sets.newHashSet(Qualifiers.SUBVIEW, Qualifiers.PROJECT));
-
- FilterResult result = executor.execute(filter);
- assertSnapshotIds(result, 3, 4);
- }
-
- @Test
- public void explicitelyUseIndexOnMsSql() {
- Filter filter = new Filter().addMeasureCriterion(new MeasureCriterion(1, ">", 400.0, false));
-
- String sql = new FilterExecutor(getSession(), new MsSql()).toSql(filter);
- assertThat(sql).contains(" WITH (INDEX(measures_sid_metric)) ");
-
- sql = new FilterExecutor(getSession(), new H2()).toSql(filter);
- assertThat(sql).doesNotContain(" WITH (INDEX(measures_sid_metric)) ");
- }
-
- private void assertSnapshotIds(FilterResult result, int... snapshotIds) {
- assertThat(result.size()).isEqualTo(snapshotIds.length);
- for (int snapshotId : snapshotIds) {
- boolean found = false;
- for (Object[] row : result.getRows()) {
- found |= result.getSnapshotId(row) == snapshotId;
- }
- if (!found) {
- fail("Snapshot id not found in results: " + snapshotId);
- }
- }
- }
-
- private void assertSortedSnapshotIds(FilterResult result, int... snapshotIds) {
- assertThat(result.size()).isEqualTo(snapshotIds.length);
- for (int index = 0; index < snapshotIds.length; index++) {
- assertThat(result.getSnapshotId(result.getRows().get(index))).isEqualTo(snapshotIds[index]);
- }
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.filters;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
-
-public class FilterResultTest {
-
- @Test
- public void sortWithNullElements() {
- List<String[]> list = Arrays.asList(new String[]{"foo"}, new String[]{null}, new String[]{"bar"}, new String[]{null}, new String[]{null}, new String[]{"toto"});
- Collections.sort(list, new FilterResult.NumericComparator(0));
-
- assertThat(list.get(0)[0], nullValue());
- assertThat(list.get(1)[0], nullValue());
- assertThat(list.get(2)[0], nullValue());
- assertThat(list.get(3)[0], is("bar"));
- assertThat(list.get(4)[0], is("foo"));
- assertThat(list.get(5)[0], is("toto"));
- }
-}
+++ /dev/null
-<dataset>
- <metrics delete_historical_data="[null]" id="1" name="lines" val_type="FLOAT" description="Lines" domain="Size"
- short_name="Lines" qualitative="false" user_managed="false" enabled="true" origin="JAV" worst_value="[null]"
- optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/>
-
- <metrics delete_historical_data="[null]" id="2" name="coverage" val_type="PERCENT" description="Coverage" domain="Tests"
- short_name="Coverage" qualitative="true" user_managed="false" enabled="true" origin="JAV" worst_value="[null]"
- optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/>
-
- <metrics delete_historical_data="[null]" id="3" name="duplicated_lines" val_type="INT" description="Duplicated lines" domain="Duplications"
- short_name="Duplications" qualitative="false" user_managed="false" enabled="true" origin="JAV" worst_value="[null]"
- optimized_best_value="[null]" best_value="[null]" direction="1" hidden="false"/>
-
-
- <!-- Java classes -->
- <projects long_name="org.sonar.foo:File1" id="4" scope="FIL" kee="project:java:org.sonar.foo:File1" qualifier="CLA" name="File1"
- root_id="1"
- description="[null]" enabled="true" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
- <projects long_name="org.sonar.foo:File2" id="5" scope="FIL" kee="project:java:org.sonar.foo:File2" qualifier="CLA" name="File2"
- root_id="1"
- description="[null]" enabled="true" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
-
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="5" created_at="2008-12-25 01:00:01.00" build_date="2008-12-25 01:00:01.00" version="1.0" project_id="4" scope="FIL" qualifier="CLA"
- root_project_id="1" root_snapshot_id="2" parent_snapshot_id="4" STATUS="P" ISLAST="true"
- path="2.4."
- depth="2"/>
-
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="6" created_at="2008-12-25 01:00:01.00" build_date="2008-12-25 01:00:01.00" version="1.0" project_id="5" scope="FIL" qualifier="CLA"
- root_project_id="1" root_snapshot_id="2" parent_snapshot_id="4" STATUS="P" ISLAST="true"
- path="2.4."
- depth="2"/>
-
-
- <!-- SNAPSHOT 5 : 500 lines and coverage 80.5% -->
- <project_measures characteristic_id="[null]" id="1" metric_id="1" value="500" snapshot_id="5"
- url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]"/>
-
- <project_measures characteristic_id="[null]" id="2" metric_id="2" value="80.5" snapshot_id="5"
- url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]"/>
-
-
- <!-- SNAPSHOT 6 : 30 lines, coverage 20.6% and 10 duplicated lines -->
- <project_measures characteristic_id="[null]" id="3" metric_id="1" value="30" snapshot_id="6"
- url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]"/>
-
- <project_measures characteristic_id="[null]" id="4" metric_id="2" value="20.6" snapshot_id="6"
- url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]"/>
-
- <project_measures characteristic_id="[null]" id="5" metric_id="3" value="10" snapshot_id="6"
- url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
- RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
- alert_status="[null]" description="[null]"/>
-</dataset>
\ No newline at end of file
+++ /dev/null
-<dataset>
- <projects long_name="java project" id="1" scope="PRJ" kee="project:java" qualifier="TRK" name="java project"
- root_id="[null]"
- description="[null]" enabled="true" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
- <projects long_name="php project" id="2" scope="PRJ" kee="project:a-php-project" qualifier="TRK" name="php project"
- root_id="[null]"
- description="[null]" enabled="true" language="php" copy_resource_id="[null]" person_id="[null]"/>
-
- <projects long_name="org.sonar.foo" id="3" scope="DIR" kee="project:java:org.sonar.foo" qualifier="PAC" name="org.sonar.foo"
- root_id="1"
- description="[null]" enabled="true" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
-
- <!-- Java project -->
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="1" created_at="2008-12-20 00:00:00.00" build_date="2008-12-20 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
- root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
- path=""
- depth="0"/>
-
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="2" created_at="2008-12-25 01:00:00.00" build_date="2008-12-25 01:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
- root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="true"
- path=""
- depth="0"/>
-
- <!-- PHP project -->
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="3" created_at="2008-12-31 02:00:00.00" build_date="2008-12-31 02:00:00.00" version="1.0" project_id="2" scope="PRJ" qualifier="TRK"
- root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="true"
- path=""
- depth="0"/>
-
- <!-- Java package -->
- <snapshots purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]" id="4" created_at="2008-12-25 01:00:01.00" build_date="2008-12-25 01:00:01.00" version="1.0" project_id="3" scope="DIR" qualifier="PAC"
- root_project_id="1" root_snapshot_id="2" parent_snapshot_id="2" STATUS="P" ISLAST="true"
- path="2."
- depth="1"/>
-
-
-</dataset>
\ No newline at end of file