]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-3621 use JSON format between rails and java components
authorSimon Brandhof <simon.brandhof@gmail.com>
Tue, 9 Oct 2012 11:49:01 +0000 (13:49 +0200)
committerSimon Brandhof <simon.brandhof@gmail.com>
Tue, 9 Oct 2012 11:49:19 +0000 (13:49 +0200)
This is the first step before the refactoring of the tables FILTERS, FILTER_COLUMNS and CRITERIA

34 files changed:
sonar-application/src/main/assembly/conf/logback.xml
sonar-core/pom.xml
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilter.java
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterContext.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterDecoder.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterExecutor.java
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSort.java
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterValueCondition.java [deleted file]
sonar-core/src/main/java/org/sonar/core/measure/MesasureFilterContext.java [deleted file]
sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterContextTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterDecoderTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterEngineTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterExecutorTest.java
sonar-server/src/dev/h2/conf/logback.xml
sonar-server/src/dev/mysql/conf/logback.xml
sonar-server/src/dev/postgresql/conf/logback.xml
sonar-server/src/main/java/org/sonar/server/filters/DateCriterion.java [deleted file]
sonar-server/src/main/java/org/sonar/server/filters/Filter.java [deleted file]
sonar-server/src/main/java/org/sonar/server/filters/FilterExecutor.java [deleted file]
sonar-server/src/main/java/org/sonar/server/filters/FilterResult.java [deleted file]
sonar-server/src/main/java/org/sonar/server/filters/MeasureCriterion.java [deleted file]
sonar-server/src/main/java/org/sonar/server/platform/Platform.java
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/main/webapp/WEB-INF/app/models/filter.rb
sonar-server/src/main/webapp/WEB-INF/app/models/filter_context.rb
sonar-server/src/main/webapp/WEB-INF/app/models/filters.rb
sonar-server/src/test/java/org/sonar/server/filters/DateCriterionTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/filters/FilterExecutorTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/filters/FilterResultTest.java [deleted file]
sonar-server/src/test/resources/org/sonar/server/filters/FilterExecutorTest/measures.xml [deleted file]
sonar-server/src/test/resources/org/sonar/server/filters/FilterExecutorTest/shared.xml [deleted file]

index 1c36ddc015ab733069e770a4e000dd1c59b862f5..63913b48eea10bf781d3527886b922bd2528900f 100644 (file)
     <level value="WARN"/>
   </logger>
 
+  <logger name="org.sonar.MEASURE_FILTER">
+    <level value="WARN"/>
+  </logger>
+
   <root>
     <level value="INFO"/>
     <appender-ref ref="SONAR_FILE"/>
index b54ae40570bfb7f3b67774322ad4c6729255208f..5dc5927228914d4b48bd6caf5c728edd9d963e75 100644 (file)
@@ -1,5 +1,6 @@
 <?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>
index d3a9ffd0b3650b61f659bc03c39d1ab6e40deddd..0fbf9f2f6d6886f4cd234b54058a6aa03ad0462b 100644 (file)
 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;
   }
 
@@ -62,18 +62,28 @@ public class MeasureFilter {
     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;
   }
 
@@ -82,11 +92,11 @@ public class MeasureFilter {
     return this;
   }
 
-  public boolean userFavourites() {
+  public boolean isOnFavourites() {
     return userFavourites;
   }
 
-  public String resourceName() {
+  public String getResourceName() {
     return resourceName;
   }
 
@@ -95,7 +105,7 @@ public class MeasureFilter {
     return this;
   }
 
-  public MeasureFilter addCondition(MeasureFilterValueCondition condition) {
+  public MeasureFilter addCondition(MeasureFilterCondition condition) {
     this.measureConditions.add(condition);
     return this;
   }
@@ -111,6 +121,7 @@ public class MeasureFilter {
   }
 
   public MeasureFilter setSortOnMetric(Metric m) {
+    this.sort.setField(MeasureFilterSort.Field.METRIC);
     this.sort.setMetric(m);
     return this;
   }
@@ -130,27 +141,27 @@ public class MeasureFilter {
     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;
   }
 
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java
new file mode 100644 (file)
index 0000000..b97ec5f
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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);
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterContext.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterContext.java
new file mode 100644 (file)
index 0000000..5c0ad12
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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();
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterDecoder.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterDecoder.java
new file mode 100644 (file)
index 0000000..7cf092b
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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;
+  }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java
new file mode 100644 (file)
index 0000000..2b5da9a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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());
+    }
+  }
+
+}
index eb66a9aa0b40451d33f75ff2956d88477e03df06..b529f5a384aabc41147f9bade3e7b6280eac302f 100644 (file)
 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;
@@ -45,24 +42,21 @@ public class MeasureFilterExecutor implements ServerComponent {
     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);
     }
@@ -70,19 +64,31 @@ public class MeasureFilterExecutor implements ServerComponent {
     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;
   }
 }
index 3abb3672664027793036044c7db61743b357ebf9..d0e2d53f7316d02436543d5a62bc160080b8fb8f 100644 (file)
@@ -28,7 +28,7 @@ class MeasureFilterSort {
 
   private Field field = Field.NAME;
   private Metric metric = null;
-  private int period = -1;
+  private Integer period = null;
   private boolean asc = true;
 
   MeasureFilterSort() {
@@ -43,8 +43,12 @@ class 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) {
@@ -92,7 +96,7 @@ class MeasureFilterSort {
         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";
         }
index e59708c846732cad0ee86ee74750cb033efa3727..3952a86396fa3d130ece23d793f241854ca35d55 100644 (file)
@@ -39,11 +39,11 @@ class MeasureFilterSql {
 
   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;
@@ -71,22 +71,22 @@ class MeasureFilterSql {
 
   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 ");
         }
@@ -101,8 +101,8 @@ class MeasureFilterSql {
 
   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 ");
@@ -115,14 +115,14 @@ class MeasureFilterSql {
     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);
     }
@@ -130,44 +130,46 @@ class MeasureFilterSql {
     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(") ");
     }
@@ -178,7 +180,7 @@ class MeasureFilterSql {
       } 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(".%'");
       }
     }
   }
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterValueCondition.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterValueCondition.java
deleted file mode 100644 (file)
index 145e7d7..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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);
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MesasureFilterContext.java b/sonar-core/src/main/java/org/sonar/core/measure/MesasureFilterContext.java
deleted file mode 100644 (file)
index c5362a3..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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;
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterContextTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterContextTest.java
new file mode 100644 (file)
index 0000000..ffd7fd6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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]");
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterDecoderTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterDecoderTest.java
new file mode 100644 (file)
index 0000000..750cd66
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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();
+
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterEngineTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterEngineTest.java
new file mode 100644 (file)
index 0000000..b92d173
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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());
+  }
+}
index 75922b5eea2628c15f7e2774991955c175c35109..e2eb14507bf190a60106307a5c634b38247a3ebe 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.core.persistence.AbstractDaoTestCase;
 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;
@@ -54,15 +55,15 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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();
 
@@ -70,9 +71,23 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
     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();
 
@@ -81,9 +96,9 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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));
@@ -100,9 +115,9 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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);
@@ -111,9 +126,9 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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);
@@ -122,9 +137,9 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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
@@ -132,9 +147,9 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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
@@ -142,18 +157,18 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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);
@@ -162,9 +177,9 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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);
@@ -173,19 +188,19 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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
@@ -193,10 +208,10 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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
@@ -204,70 +219,70 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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);
@@ -275,11 +290,11 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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);
@@ -287,18 +302,18 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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
@@ -307,26 +322,26 @@ public class MeasureFilterExecutorTest extends AbstractDaoTestCase {
   }
 
   @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));
index 127e47ad786c04b05cc6f2ed41725f508cdfd08a..3ea98589f8820926e4d8a28536c6bd8cfa3bc864 100644 (file)
     <level value="DEBUG"/>
   </logger>
 
+  <logger name="org.sonar.MEASURE_FILTER">
+    <level value="DEBUG"/>
+  </logger>
+
   <root>
     <level value="INFO"/>
     <appender-ref ref="STDOUT"/>
index 127e47ad786c04b05cc6f2ed41725f508cdfd08a..3ea98589f8820926e4d8a28536c6bd8cfa3bc864 100644 (file)
     <level value="DEBUG"/>
   </logger>
 
+  <logger name="org.sonar.MEASURE_FILTER">
+    <level value="DEBUG"/>
+  </logger>
+
   <root>
     <level value="INFO"/>
     <appender-ref ref="STDOUT"/>
index 127e47ad786c04b05cc6f2ed41725f508cdfd08a..3ea98589f8820926e4d8a28536c6bd8cfa3bc864 100644 (file)
     <level value="DEBUG"/>
   </logger>
 
+  <logger name="org.sonar.MEASURE_FILTER">
+    <level value="DEBUG"/>
+  </logger>
+
   <root>
     <level value="INFO"/>
     <appender-ref ref="STDOUT"/>
diff --git a/sonar-server/src/main/java/org/sonar/server/filters/DateCriterion.java b/sonar-server/src/main/java/org/sonar/server/filters/DateCriterion.java
deleted file mode 100644 (file)
index b1c2903..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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();
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/filters/Filter.java b/sonar-server/src/main/java/org/sonar/server/filters/Filter.java
deleted file mode 100644 (file)
index 351477d..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * 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);
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/filters/FilterExecutor.java b/sonar-server/src/main/java/org/sonar/server/filters/FilterExecutor.java
deleted file mode 100644 (file)
index c3d0f26..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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(), '*', '%')));
-    }
-  }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/filters/FilterResult.java b/sonar-server/src/main/java/org/sonar/server/filters/FilterResult.java
deleted file mode 100644 (file)
index 8798753..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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);
-    }
-  }
-}
-
diff --git a/sonar-server/src/main/java/org/sonar/server/filters/MeasureCriterion.java b/sonar-server/src/main/java/org/sonar/server/filters/MeasureCriterion.java
deleted file mode 100644 (file)
index 2413df5..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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();
-  }
-}
index 56ae61b787ffc7c1ab1c249cfccd1499099a438f..83ae16377ae58bd9293aae79f40ab1b9dac131e4 100644 (file)
@@ -42,13 +42,12 @@ import org.sonar.core.config.Logback;
 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;
@@ -65,25 +64,14 @@ import org.sonar.server.charts.ChartFactory;
 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;
 
@@ -203,7 +191,6 @@ public final class Platform {
     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);
@@ -233,6 +220,9 @@ public final class Platform {
     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);
index b588f82a9245d4178f344c4d6673231faa06f3de..9f52e40f9b19403d1acd5d54999df77c520b1d40 100644 (file)
@@ -38,16 +38,14 @@ import org.sonar.api.resources.ResourceTypes;
 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;
@@ -57,26 +55,14 @@ import org.sonar.core.workflow.WorkflowEngine;
 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;
@@ -97,8 +83,8 @@ public final class JRubyFacade {
     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() {
@@ -313,7 +299,7 @@ public final class JRubyFacade {
 
   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) {
@@ -509,10 +495,10 @@ public final class JRubyFacade {
     // 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());
     }
   }
 }
index 07c04795132032d1bdc10a22574941ff02dec5f4..471cc4575362f190284d0523bf9202c07d729784 100644 (file)
@@ -168,7 +168,7 @@ class Filter < ActiveRecord::Base
   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
index 060e743aae4fe7a3395b99f160fbf812d6f448be..f3346ab76347cf1d82684bea628484ef02280cbd 100644 (file)
 
   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
index c687797f14d56469853c03ed2ecb5c0c71d82059..67198337ad83dca1f544bd337df84bdbd205bf73 100644 (file)
@@ -21,82 +21,71 @@ class Filters
 
   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
 
@@ -104,51 +93,39 @@ class Filters
     #----- 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
diff --git a/sonar-server/src/test/java/org/sonar/server/filters/DateCriterionTest.java b/sonar-server/src/test/java/org/sonar/server/filters/DateCriterionTest.java
deleted file mode 100644 (file)
index 7f25151..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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));
-  }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/filters/FilterExecutorTest.java b/sonar-server/src/test/java/org/sonar/server/filters/FilterExecutorTest.java
deleted file mode 100644 (file)
index 8ed6c98..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * 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]);
-    }
-  }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/filters/FilterResultTest.java b/sonar-server/src/test/java/org/sonar/server/filters/FilterResultTest.java
deleted file mode 100644 (file)
index afb3565..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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"));
-  }
-}
diff --git a/sonar-server/src/test/resources/org/sonar/server/filters/FilterExecutorTest/measures.xml b/sonar-server/src/test/resources/org/sonar/server/filters/FilterExecutorTest/measures.xml
deleted file mode 100644 (file)
index 73a9937..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<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
diff --git a/sonar-server/src/test/resources/org/sonar/server/filters/FilterExecutorTest/shared.xml b/sonar-server/src/test/resources/org/sonar/server/filters/FilterExecutorTest/shared.xml
deleted file mode 100644 (file)
index cdb5103..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<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