]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4569 The 'Bulk Deletion'>'Ghosts' page should display ALL projects whose defini...
authorJulien Lancelot <julien.lancelot@gmail.com>
Wed, 28 Aug 2013 09:09:58 +0000 (11:09 +0200)
committerJulien Lancelot <julien.lancelot@gmail.com>
Wed, 28 Aug 2013 09:09:58 +0000 (11:09 +0200)
sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java
sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java
sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml
sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java
sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture-including-ghost-projects-and-technical-project.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture-including-technical-project-and-not-finished-projects.xml [deleted file]
sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/bulk_deletion_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/views/bulk_deletion/ghosts.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/bulk_deletion/index.html.erb
sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java

index db0ce0dca7b8ff9a2490b622159e915d3e191217..da292f939b093dfaa3c2f76d3d81db4326072b8f 100644 (file)
@@ -201,28 +201,46 @@ public class ResourceDao {
     }
   }
 
-  public List<Component> selectComponentsByQualifiers(Collection<String> qualifiers) {
+  public List<Component> selectProjectsByQualifiers(Collection<String> qualifiers) {
     if (qualifiers.isEmpty()) {
       return Collections.emptyList();
     }
     SqlSession session = mybatis.openSession();
     try {
-      return toComponents(session.getMapper(ResourceMapper.class).selectComponentsByQualifiers(qualifiers));
+      return toComponents(session.getMapper(ResourceMapper.class).selectProjectsByQualifiers(qualifiers));
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
   /**
-   * Return enabled components including not completed ones, ie without snapshots or without snapshot having islast=true
+   * Return enabled projects including not completed ones, ie without snapshots or without snapshot having islast=true
    */
-  public List<Component> selectComponentsIncludingNotCompletedOnesByQualifiers(Collection<String> qualifiers) {
+  public List<Component> selectProjectsIncludingNotCompletedOnesByQualifiers(Collection<String> qualifiers) {
     if (qualifiers.isEmpty()) {
       return Collections.emptyList();
     }
     SqlSession session = mybatis.openSession();
     try {
-      return toComponents(session.getMapper(ResourceMapper.class).selectComponentsIncludingNotCompletedOnesByQualifiers(qualifiers));
+      return toComponents(session.getMapper(ResourceMapper.class).selectProjectsIncludingNotCompletedOnesByQualifiers(qualifiers));
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  /**
+   * Return ghosts projects :
+   * - not enabled projects
+   * - enabled projects without snapshot having islast=true
+   * - enabled projects without snapshot
+   */
+  public List<Component> selectGhostsProjects(Collection<String> qualifiers) {
+    if (qualifiers.isEmpty()) {
+      return Collections.emptyList();
+    }
+    SqlSession session = mybatis.openSession();
+    try {
+      return toComponents(session.getMapper(ResourceMapper.class).selectGhostsProjects(qualifiers));
     } finally {
       MyBatis.closeQuietly(session);
     }
index 5b947c7bfa8d810d4eaa98b98f63cc7c7bcb7904..488dbe38b2b22fe4ab1ebee0ab209ebbd711a150 100644 (file)
@@ -74,9 +74,11 @@ public interface ResourceMapper {
   List<Integer> selectAuthorizedChildrenComponentIds(@Param("componentRootKeys") Collection<String> componentRootKeys,
                                                      @Param("userId") @Nullable Integer userId, @Param("role") String role);
 
-  List<ResourceDto> selectComponentsByQualifiers(@Param("qualifiers") Collection<String> qualifier);
+  List<ResourceDto> selectProjectsIncludingNotCompletedOnesByQualifiers(@Param("qualifiers") Collection<String> qualifier);
 
-  List<ResourceDto> selectComponentsIncludingNotCompletedOnesByQualifiers(@Param("qualifiers") Collection<String> qualifier);
+  List<ResourceDto> selectProjectsByQualifiers(@Param("qualifiers") Collection<String> qualifier);
+
+  List<ResourceDto> selectGhostsProjects(@Param("qualifiers") Collection<String> qualifier);
 
   void insert(ResourceDto resource);
 
index 83f8185faea8d055119165819893f6384120bc10..b74a7eb0d87b2ffe664b75fe873da18f09c1b09b 100644 (file)
@@ -3,6 +3,22 @@
 
 <mapper namespace="org.sonar.core.resource.ResourceMapper">
 
+  <sql id="resourceColumns">
+    p.id,
+    p.kee as key,
+    p.name as name,
+    p.long_name as longName,
+    p.root_id as rootId,
+    p.scope as scope,
+    p.qualifier as qualifier,
+    p.enabled as enabled,
+    p.description as description,
+    p.language as language,
+    p.copy_resource_id as copyResourceId,
+    p.person_id as personId,
+    p.created_at as createdAt
+  </sql>
+
   <resultMap id="snapshotResultMap" type="Snapshot">
     <id property="id" column="id"/>
     <result property="parentId" column="parent_snapshot_id"/>
     </where>
   </select>
 
-  <select id="selectComponentsByQualifiers" parameterType="map" resultMap="resourceResultMap">
+  <select id="selectProjectsIncludingNotCompletedOnesByQualifiers" parameterType="map" resultMap="resourceResultMap">
     select * from projects p
-    inner join snapshots s on s.project_id=p.id
     <where>
       <if test="qualifiers != null and qualifiers.size() > 0">
         and <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")">p.qualifier=#{qualifier}
       </if>
       and p.enabled=${_true}
       and p.copy_resource_id is null
-      and s.islast=${_true}
     </where>
   </select>
 
-  <select id="selectComponentsIncludingNotCompletedOnesByQualifiers" parameterType="map" resultMap="resourceResultMap">
-    select * from projects p
+  <select id="selectProjectsByQualifiers" parameterType="map" resultMap="resourceResultMap">
+    <include refid="selectProjectsByQualifiersQuery" />
+  </select>
+
+  <sql id="selectProjectsByQualifiersQuery">
+    select <include refid="resourceColumns"/> from projects p
+    inner join snapshots s on s.project_id=p.id
     <where>
       <if test="qualifiers != null and qualifiers.size() > 0">
         and <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")">p.qualifier=#{qualifier}
       </if>
       and p.enabled=${_true}
       and p.copy_resource_id is null
+      and s.islast=${_true}
+    </where>
+  </sql>
+
+  <select id="selectGhostsProjects" parameterType="map" resultType="Resource">
+    select <include refid="resourceColumns"/> from projects p
+    left join (<include refid="selectProjectsByQualifiersQuery" />) availableProjects on availableProjects.id=p.id
+    <where>
+      and availableProjects.id is null
+      <if test="qualifiers != null and qualifiers.size() > 0">
+        and <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator=" or " close=")">p.qualifier=#{qualifier}
+        </foreach>
+      </if>
+      and p.copy_resource_id is null
     </where>
   </select>
 
index cd77a7eed8ad1e4d13f7515a123294c7991046d1..a3b904595aae6b5b187e506e829a277f8eeb8c9a 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.core.resource;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
 import org.apache.ibatis.session.SqlSession;
 import org.junit.Before;
 import org.junit.Test;
@@ -28,6 +30,8 @@ import org.sonar.api.resources.Scopes;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 
+import javax.annotation.Nullable;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -311,26 +315,46 @@ public class ResourceDaoTest extends AbstractDaoTestCase {
   }
 
   @Test
-  public void should_select_components_by_qualifiers(){
-    setupData("fixture-including-technical-project-and-not-finished-projects");
+  public void should_select_projects_by_qualifiers(){
+    setupData("fixture-including-ghost-projects-and-technical-project");
 
-    List<Component> components = dao.selectComponentsByQualifiers(newArrayList("TRK"));
+    List<Component> components = dao.selectProjectsByQualifiers(newArrayList("TRK"));
     assertThat(components).hasSize(1);
     assertThat(components.get(0).key()).isEqualTo("org.struts:struts");
     assertThat(((ComponentDto)components.get(0)).getId()).isEqualTo(1L);
 
-    assertThat(dao.selectComponentsIncludingNotCompletedOnesByQualifiers(newArrayList("unknown"))).isEmpty();
-    assertThat(dao.selectComponentsIncludingNotCompletedOnesByQualifiers(Collections.<String>emptyList())).isEmpty();
+    assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(newArrayList("unknown"))).isEmpty();
+    assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(Collections.<String>emptyList())).isEmpty();
+  }
+
+  @Test
+  public void should_select_projects_including_not_finished_by_qualifiers(){
+    setupData("fixture-including-ghost-projects-and-technical-project");
+
+    List<Component> components = dao.selectProjectsIncludingNotCompletedOnesByQualifiers(newArrayList("TRK"));
+    assertThat(getKeys(components)).containsOnly("org.struts:struts", "org.apache.shindig", "org.sample:sample");
+
+    assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(newArrayList("unknown"))).isEmpty();
+    assertThat(dao.selectProjectsIncludingNotCompletedOnesByQualifiers(Collections.<String>emptyList())).isEmpty();
   }
 
   @Test
-  public void should_select_components_including_not_finished_by_qualifiers(){
-    setupData("fixture-including-technical-project-and-not-finished-projects");
+  public void should_select_ghosts_projects_by_qualifiers(){
+    setupData("fixture-including-ghost-projects-and-technical-project");
 
-    List<Component> components = dao.selectComponentsIncludingNotCompletedOnesByQualifiers(newArrayList("TRK"));
-    assertThat(components).hasSize(3);
+    List<Component> components = dao.selectGhostsProjects(newArrayList("TRK"));
+    assertThat(getKeys(components)).containsOnly("org.apache.shindig", "org.sample:sample", "org.apache:tika");
+
+    assertThat(dao.selectGhostsProjects(newArrayList("unknown"))).isEmpty();
+    assertThat(dao.selectGhostsProjects(Collections.<String>emptyList())).isEmpty();
+  }
 
-    assertThat(dao.selectComponentsIncludingNotCompletedOnesByQualifiers(newArrayList("unknown"))).isEmpty();
-    assertThat(dao.selectComponentsIncludingNotCompletedOnesByQualifiers(Collections.<String>emptyList())).isEmpty();
+  private List<String> getKeys(final List<Component> components){
+    return newArrayList(Iterables.transform(components, new Function<Component, String>() {
+      @Override
+      public String apply(@Nullable Component input) {
+        return input.key();
+      }
+    }));
   }
 }
diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture-including-ghost-projects-and-technical-project.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture-including-ghost-projects-and-technical-project.xml
new file mode 100644 (file)
index 0000000..07f813b
--- /dev/null
@@ -0,0 +1,111 @@
+<dataset>
+
+  <!-- root project -->
+  <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
+            description="the description" long_name="Apache Struts"
+            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+  <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+               status="P" islast="[true]" 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]"
+               depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+               version="[null]" path=""/>
+  <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+             status="P" islast="[false]" 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]"
+             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-01 13:58:00.00" build_date="2008-12-01 13:58:00.00"
+             version="[null]" path=""/>
+
+  <!-- project -->
+  <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core"
+            scope="PRJ" qualifier="BRC" long_name="Struts Core"
+            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+  <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+               status="P" islast="[true]" 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]"
+               depth="[null]" scope="PRJ" qualifier="BRC" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+               version="[null]" path="1."/>
+
+  <!-- directory -->
+  <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts"
+              name="org.struts" root_id="1"
+              description="[null]"
+              enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+  <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+               status="P" islast="[true]" 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]"
+               depth="[null]" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+               version="[null]" path="1.2."/>
+
+  <!-- file -->
+  <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" kee="org.struts:struts:org.struts.RequestContext"
+            name="RequestContext" root_id="1"
+            description="[null]"
+            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+
+  <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1"
+               status="P" islast="[true]" 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]"
+               depth="[null]" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+               version="[null]" path="1.2.3."/>
+
+  <!-- technical project -->
+  <projects id="5" root_id="[null]" scope="PRJ" qualifier="TRK" kee="COPYorg.struts:struts" name="Struts"
+            description="the description" long_name="Apache Struts"
+            enabled="[true]" language="java" copy_resource_id="1" person_id="[null]"/>
+
+  <!-- project without snapshot islast=true-->
+  <projects id="6" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache.shindig" name="Shinding"
+            description="the description" long_name="Shinding"
+            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+  <snapshots id="6" project_id="6" parent_snapshot_id="[null]" root_project_id="6" root_snapshot_id="[null]"
+             status="P" islast="[false]" 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]"
+             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+             version="[null]" path=""/>
+
+  <!-- project without snapshot -->
+  <projects id="7" root_id="[null]" kee="org.sample:sample" name="Sample"
+            scope="PRJ" qualifier="TRK" long_name="Sample"
+            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+
+  <!-- project not enabled -->
+  <projects id="8" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache:tika" name="Tika"
+            description="the description" long_name="Tika"
+            enabled="[false]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+  <snapshots id="8" project_id="8" parent_snapshot_id="[null]" root_project_id="8" root_snapshot_id="[null]"
+             status="P" islast="[true]" 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]"
+             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+             version="[null]" path=""/>
+
+
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture-including-technical-project-and-not-finished-projects.xml b/sonar-core/src/test/resources/org/sonar/core/resource/ResourceDaoTest/fixture-including-technical-project-and-not-finished-projects.xml
deleted file mode 100644 (file)
index 07f813b..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-<dataset>
-
-  <!-- root project -->
-  <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
-            description="the description" long_name="Apache Struts"
-            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-  <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
-               status="P" islast="[true]" 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]"
-               depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
-               version="[null]" path=""/>
-  <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
-             status="P" islast="[false]" 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]"
-             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-01 13:58:00.00" build_date="2008-12-01 13:58:00.00"
-             version="[null]" path=""/>
-
-  <!-- project -->
-  <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core"
-            scope="PRJ" qualifier="BRC" long_name="Struts Core"
-            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-  <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
-               status="P" islast="[true]" 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]"
-               depth="[null]" scope="PRJ" qualifier="BRC" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
-               version="[null]" path="1."/>
-
-  <!-- directory -->
-  <projects long_name="org.struts" id="3" scope="DIR" qualifier="PAC" kee="org.struts:struts:org.struts"
-              name="org.struts" root_id="1"
-              description="[null]"
-              enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-  <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
-               status="P" islast="[true]" 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]"
-               depth="[null]" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
-               version="[null]" path="1.2."/>
-
-  <!-- file -->
-  <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="CLA" kee="org.struts:struts:org.struts.RequestContext"
-            name="RequestContext" root_id="1"
-            description="[null]"
-            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
-  <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1"
-               status="P" islast="[true]" 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]"
-               depth="[null]" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
-               version="[null]" path="1.2.3."/>
-
-  <!-- technical project -->
-  <projects id="5" root_id="[null]" scope="PRJ" qualifier="TRK" kee="COPYorg.struts:struts" name="Struts"
-            description="the description" long_name="Apache Struts"
-            enabled="[true]" language="java" copy_resource_id="1" person_id="[null]"/>
-
-  <!-- project without snapshot islast=true-->
-  <projects id="6" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache.shindig" name="Shinding"
-            description="the description" long_name="Shinding"
-            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-  <snapshots id="6" project_id="6" parent_snapshot_id="[null]" root_project_id="6" root_snapshot_id="[null]"
-             status="P" islast="[false]" 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]"
-             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
-             version="[null]" path=""/>
-
-  <!-- project without snapshot -->
-  <projects id="7" root_id="[null]" kee="org.sample:sample" name="Sample"
-            scope="PRJ" qualifier="TRK" long_name="Sample"
-            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-
-  <!-- project not enabled -->
-  <projects id="8" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.apache:tika" name="Tika"
-            description="the description" long_name="Tika"
-            enabled="[false]" language="java" copy_resource_id="[null]" person_id="[null]"/>
-  <snapshots id="8" project_id="8" parent_snapshot_id="[null]" root_project_id="8" root_snapshot_id="[null]"
-             status="P" islast="[true]" 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]"
-             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
-             version="[null]" path=""/>
-
-
-
-</dataset>
index cd6aff52739d30319389a92f7805a693b90a9eb1..a7942f193bafc5ed3b3cb898d87a6f6345bb3e13 100644 (file)
@@ -45,13 +45,19 @@ public class DefaultRubyComponentService implements RubyComponentService {
 
   public DefaultComponentQueryResult find(Map<String, Object> params) {
     ComponentQuery query = toQuery(params);
-    List<Component> components = resourceDao.selectComponentsByQualifiers(query.qualifiers());
+    List<Component> components = resourceDao.selectProjectsByQualifiers(query.qualifiers());
     return finder.find(query, components);
   }
 
   public DefaultComponentQueryResult findWithUncompleteProjects(Map<String, Object> params) {
     ComponentQuery query = toQuery(params);
-    List<Component> components = resourceDao.selectComponentsIncludingNotCompletedOnesByQualifiers(query.qualifiers());
+    List<Component> components = resourceDao.selectProjectsIncludingNotCompletedOnesByQualifiers(query.qualifiers());
+    return finder.find(query, components);
+  }
+
+  public DefaultComponentQueryResult findGhostsProjects(Map<String, Object> params) {
+    ComponentQuery query = toQuery(params);
+    List<Component> components = resourceDao.selectGhostsProjects(query.qualifiers());
     return finder.find(query, components);
   }
 
index b4c2f9c12be677838c5382dec5f7a01e984ce91c..51dbf844be1a2a0a1089822e6029a9c98d159473 100644 (file)
@@ -31,21 +31,12 @@ class BulkDeletionController < ApplicationController
         
     @tabs = deletable_qualifiers
     
-    @selected_tab = params[:resource_type]
+    @selected_tab = params[:qualifiers]
     @selected_tab = 'TRK' unless @tabs.include?(@selected_tab)
 
-    # Search for resources having snapshot with islast column to true
-    # SONAR-4569
-    conditions = "resource_index.qualifier=:qualifier AND projects.qualifier=:qualifier AND projects.enabled=:enabled AND snapshots.islast=:islast"
-    values = {:qualifier => @selected_tab, :enabled => true, :islast => true}
-    if params[:name_filter] && !params[:name_filter].blank?
-      conditions += " AND resource_index.kee LIKE :kee"
-      values[:kee] = params[:name_filter].strip.downcase + '%'
-    end
-    @resources = Project.all(:select => 'distinct(resource_index.resource_id),projects.id,projects.name,projects.kee,projects.long_name',
-                              :conditions => [conditions, values],
-                              :joins => [:resource_index, :snapshots])
-    @resources = Api::Utils.insensitive_sort!(@resources){|r| r.name}
+    params['pageSize'] = 20
+    params['qualifiers'] = @selected_tab
+    @query_result = Internal.component_api.find(params)
   end
 
   def ghosts
@@ -55,23 +46,12 @@ class BulkDeletionController < ApplicationController
     end
       
     @tabs = deletable_qualifiers
-    
-    conditions = "scope=:scope AND qualifier IN (:qualifiers) AND status=:status"
-    values = {:scope => 'PRJ', :qualifiers => @tabs}
-    unprocessed_project_ids = Snapshot.all(
-        :select => 'project_id',
-        :conditions => [conditions, values.merge({:status => Snapshot::STATUS_UNPROCESSED})]).map(&:project_id).uniq
-    already_processed_project_ids = Snapshot.all(
-        :select => 'project_id',
-        :conditions => [conditions + " AND project_id IN (:pids)", values.merge({:status => Snapshot::STATUS_PROCESSED, :pids => unprocessed_project_ids})]).map(&:project_id).uniq
 
-    # SONAR-4569
-    # Detect active projects without any snapshots or with no snapshot having islast column to true
-    projects_not_having_snapshots_islast_to_true =
-        Project.find_by_sql ["SELECT p.id FROM projects p WHERE p.enabled=? AND p.scope=? AND p.qualifier IN (?) AND NOT EXISTS (SELECT id FROM snapshots WHERE islast=? and project_id=p.id)",
-                             true, 'PRJ', @tabs, true]
+    params['pageSize'] = -1
+    params['qualifiers'] = @tabs
+    @query_result = Internal.component_api.findGhostsProjects(params)
 
-    @ghosts = Project.all(:conditions => ["id IN (?)", unprocessed_project_ids - already_processed_project_ids + projects_not_having_snapshots_islast_to_true])
+    @ghosts = @query_result.components
     
     @ghosts_by_qualifier = {}
     @ghosts.each do |p|
index f355ea48a509d138ca2a83ac9b173b9358af024e..e141f0ef2b88c7cc297bcd7c3d3ca2caeb3f1fb6 100644 (file)
@@ -40,9 +40,9 @@
         <td>
           <ul>
       <%
-             ghosts.sort {|x,y| x.name <=> y.name}.each_with_index do |resource, index| 
+             ghosts.sort {|x,y| x.name <=> y.name}.each do |resource|
       %>
-          <li><%= h resource.name -%> <span class="small gray">( <%= h resource.key -%> )</span></li>
+              <li><%= h resource.name -%> <span class="small gray">( <%= h resource.key -%> )</span></li>
       <% 
              end
       %>
index 29d2118ae521c6b3e268f862c17327354631175e..721bc9be79ba28fd7c12e923e897b4411b5aaf54 100644 (file)
@@ -3,7 +3,7 @@
 <ul class="tabs">
 <% @tabs.each do |tab| %>
   <li>
-    <a href="<%= url_for :action => 'index', :resource_type => tab %>" <%= "class='selected'" if @selected_tab==tab -%> id="tab-<%= u tab -%>"><%= message('qualifiers.' + tab) -%></a>
+    <a href="<%= url_for :action => 'index', :qualifiers => tab %>" <%= "class='selected'" if @selected_tab==tab -%> id="tab-<%= u tab -%>"><%= message('qualifiers.' + tab) -%></a>
   </li>
 <% end %>
   <li>
 <div class="tabs-panel marginbottom10">
 
 <%
-  found_resources_count = @resources.size
-  found_resources_ids = @resources.map {|r| r.id.to_s}.join(',')
-  page_size = (params[:page_size] && params[:page_size].to_i) || 20
+  found_resources_count = @query_result.paging.total
+  found_resources_ids =  @query_result.components.map {|r| r.id.to_s}.join(',')
 %>
 
   <% form_tag( {:action => 'index'}, :method => :get ) do %>
-    <%= message('bulk_deletion.resource_name_filter_by_name') -%> <input type="text" id="resource_filter" name="name_filter" size="40px" value="<%= h params[:name_filter] -%>"/>
-    <input type="hidden" name="resource_type" value="<%= @selected_tab -%>"/>
+    <%= message('bulk_deletion.resource_name_filter_by_name') -%> <input type="text" id="resource_filter" name="names" size="40px" value="<%= h params[:names] -%>"/>
+    <input type="hidden" name="qualifiers" value="<%= @selected_tab -%>"/>
     <%= submit_tag message('bulk_deletion.filter'), :id => 'filter_resources' %>
   <% end %>
 
-  <% if @resources.empty? %>
+  <% if  @query_result.components.empty? %>
     <br/>
     <%= message('no_results') -%>
   <% else %>
 
-    <% form_remote_tag( :url => {:action => 'delete_resources'}, :loading => "window.location='#{url_for :action => 'pending_deletions', :resource_type => @selected_tab}';") do %>
-
-    <table class="data" id="resources-to-delete">
-      <tfoot>
-        <tr>
-          <td colspan="2"><%= paginate @resources, {:page_size => page_size} %></td>
-        </tr>
-        <tr>
-          <td colspan="2">
-            <input id="delete_resources" class="action red-button" type="submit" value="<%= message('delete') -%>" onclick="return checkBeforeDeleting();" name="commit">
-          </td>
-        </tr>
-      </tfoot>
-      <thead>
-        <tr>
-          <th><input id="r-all" type="checkbox" onclick="selectOrDeselect()"></th>
-          <th>
-            <span>&laquo; <%= message('bulk_deletion.select_all') -%></span>
-            <% if found_resources_count - @resources.size > 0 %>
-              <a id="select_all_action" style="padding-left: 10px; font-weight: normal; display: none"
-                 href="#" onclick="handleSelectAllAction(); return false;"><%= message('bulk_deletion.select_all_x_resources', :params => found_resources_count) -%></a>
-              <input type="hidden" id="all_resources" name="all_resources" value=""/>
-            <% end %>
-          </th>
-          <th></th>
-        </tr>
-      </thead>
-      <tbody>
-      <% @resources.each_with_index do |resource, index| %>
-        <tr class="<%= cycle 'even', 'odd' -%>">
-          <td class="thin">
-            <input id="r-<%= index -%>" type="checkbox" value="<%= resource.id -%>" name="resources[]">
-          </td>
-          <td>
-            <%= h resource.name -%>
-          </td>
-          <td>
-            <span class="small gray"><%= h resource.key -%></span></td>
-          </td>
-        </tr>
-      <% end %>
-      </tbody>
-    </table>
-
+    <% form_remote_tag( :url => {:action => 'delete_resources'}, :loading => "window.location='#{url_for :action => 'pending_deletions', :qualifiers => @selected_tab}';") do %>
+      <table class="data" id="resources-to-delete">
+        <thead>
+          <tr>
+            <th><input id="r-all" type="checkbox" onclick="selectOrDeselect()"></th>
+            <th>
+              <span>&laquo; <%= message('bulk_deletion.select_all') -%></span>
+              <% if found_resources_count - @query_result.components.size > 0 %>
+                <a id="select_all_action" style="padding-left: 10px; font-weight: normal; display: none"
+                   href="#" onclick="handleSelectAllAction(); return false;"><%= message('bulk_deletion.select_all_x_resources', :params => found_resources_count) -%></a>
+                <input type="hidden" id="all_resources" name="all_resources" value=""/>
+              <% end %>
+            </th>
+            <th></th>
+          </tr>
+        </thead>
+        <tbody>
+        <% @query_result.components.each_with_index do |resource, index| %>
+          <tr class="<%= cycle 'even', 'odd' -%>">
+            <td class="thin">
+              <input id="r-<%= index -%>" type="checkbox" value="<%= resource.id -%>" name="resources[]">
+            </td>
+            <td>
+              <%= h resource.name -%>
+            </td>
+            <td>
+              <span class="small gray"><%= h resource.key -%></span></td>
+            </td>
+          </tr>
+        <% end %>
+        </tbody>
+        <%= paginate_java(@query_result.paging, :colspan => 3, :id => 'projects-bulk-deletion-foot', :include_loading_icon => true) { |label, page_id|
+              link_to(label, params.merge({:pageIndex => page_id}))
+            }
+        %>
+        <input id="delete_resources" class="action red-button" type="submit" value="<%= message('delete') -%>" onclick="return checkBeforeDeleting();" name="commit">
+      </table>
     <% end %>
 
     <script>
@@ -99,7 +91,7 @@
         $$('tbody input').each(function(input) {
           input.checked = status;
         });
-        <% if found_resources_count - @resources.size > 0 %>
+        <% if found_resources_count - @query_result.components.size > 0 %>
         selectNotAllResources();
         if (status) {
           $('select_all_action').show();
index 3b166fd94265292ef36302b8e8abe78da4db28d0..cf40957c8fe51d9bc06ecb0c43d3143f00d02d7b 100644 (file)
@@ -55,6 +55,24 @@ public class DefaultRubyComponentServiceTest {
     assertThat(componentService.findByKey("struts")).isEqualTo(component);
   }
 
+  @Test
+  public void should_find() {
+    List<String> qualifiers = newArrayList("TRK");
+
+    Map<String, Object> map = newHashMap();
+    map.put("keys", newArrayList("org.codehaus.sonar"));
+    map.put("names", newArrayList("Sonar"));
+    map.put("qualifiers", qualifiers);
+    map.put("pageSize", 10l);
+    map.put("pageIndex", 50);
+    map.put("sort", "NAME");
+    map.put("asc", true);
+
+    componentService.find(map);
+    verify(resourceDao).selectProjectsByQualifiers(anyListOf(String.class));
+    verify(finder).find(any(ComponentQuery.class), anyListOf(Component.class));
+  }
+
   @Test
   public void should_find_with_uncomplete_projects() {
     List<String> qualifiers = newArrayList("TRK");
@@ -69,12 +87,12 @@ public class DefaultRubyComponentServiceTest {
     map.put("asc", true);
 
     componentService.findWithUncompleteProjects(map);
-    verify(resourceDao).selectComponentsIncludingNotCompletedOnesByQualifiers(anyListOf(String.class));
+    verify(resourceDao).selectProjectsIncludingNotCompletedOnesByQualifiers(anyListOf(String.class));
     verify(finder).find(any(ComponentQuery.class), anyListOf(Component.class));
   }
 
   @Test
-  public void should_find() {
+  public void should_find_ghosts_projects() {
     List<String> qualifiers = newArrayList("TRK");
 
     Map<String, Object> map = newHashMap();
@@ -86,8 +104,8 @@ public class DefaultRubyComponentServiceTest {
     map.put("sort", "NAME");
     map.put("asc", true);
 
-    componentService.find(map);
-    verify(resourceDao).selectComponentsByQualifiers(anyListOf(String.class));
+    componentService.findGhostsProjects(map);
+    verify(resourceDao).selectGhostsProjects(anyListOf(String.class));
     verify(finder).find(any(ComponentQuery.class), anyListOf(Component.class));
   }