]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19256 refactor project links to use entity
authorBenjamin Campomenosi <109955405+benjamin-campomenosi-sonarsource@users.noreply.github.com>
Wed, 28 Jun 2023 09:12:04 +0000 (11:12 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 28 Jun 2023 20:03:01 +0000 (20:03 +0000)
20 files changed:
server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectanalysis/step/PersistProjectLinksStepIT.java
server/sonar-ce-task-projectanalysis/src/it/java/org/sonar/ce/task/projectexport/steps/ExportLinksStepIT.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistProjectLinksStep.java
server/sonar-db-dao/src/it/java/org/sonar/db/component/ProjectLinkDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/project/ProjectDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/user/RoleDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/project/ProjectDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/project/ProjectMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/user/RoleDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/user/RoleMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/project/ProjectMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/user/RoleMapper.xml
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectLinkDbTester.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/project/ws/SearchMyProjectsActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/projectlink/ws/DeleteActionIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/projectlink/ws/SearchActionIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/project/ws/SearchMyProjectsData.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/project/ws/SearchMyProjectsDataTest.java

index 5f35be876107a3bc561d86a9032ba63b9f477ef6..c0469bda4b8f10fe8cd56e9f691ed8cc40661c91 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.ce.task.projectanalysis.step;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -37,10 +38,11 @@ import org.sonar.core.util.UuidFactory;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.component.ProjectLinkDto;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
+import org.sonar.server.project.Project;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -64,6 +66,8 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Rule
   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
 
+  private ProjectData project;
+
   private PersistProjectLinksStep underTest = new PersistProjectLinksStep(analysisMetadataHolder, db.getDbClient(), treeRootHolder, reportReader, UuidFactoryFast.getInstance());
 
   @Override
@@ -71,6 +75,12 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
     return underTest;
   }
 
+  @Before
+  public void setup(){
+    this.project = db.components().insertPrivateProject();
+    analysisMetadataHolder.setProject(Project.fromProjectDtoWithTags(project.getProjectDto()));
+  }
+
   @Test
   public void no_effect_if_branch_is_not_main() {
     DbClient dbClient = mock(DbClient.class);
@@ -88,8 +98,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void add_links_on_project() {
     mockBranch(true);
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
-
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
     // project
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
@@ -103,7 +112,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
 
     underTest.execute(new TestComputationStepContext());
 
-    assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), "ABCD"))
+    assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), project.projectUuid()))
       .extracting(ProjectLinkDto::getType, ProjectLinkDto::getHref, ProjectLinkDto::getName)
       .containsExactlyInAnyOrder(
         tuple("homepage", "http://www.sonarqube.org", null),
@@ -115,10 +124,9 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void nothing_to_do_when_link_already_exists() {
     mockBranch(true);
-    ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD")).getMainBranchComponent();
-    db.componentLinks().insertProvidedLink(project, l -> l.setType("homepage").setName("Home").setHref("http://www.sonarqube.org"));
+    db.projectLinks().insertProvidedLink(project.getProjectDto(), l -> l.setType("homepage").setName("Home").setHref("http://www.sonarqube.org"));
 
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
 
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
@@ -128,7 +136,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
 
     underTest.execute(new TestComputationStepContext());
 
-    assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), "ABCD"))
+    assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), project.projectUuid()))
       .extracting(ProjectLinkDto::getType, ProjectLinkDto::getHref)
       .containsExactlyInAnyOrder(tuple("homepage", "http://www.sonarqube.org"));
   }
@@ -136,7 +144,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void do_not_add_links_on_module() {
     mockBranch(true);
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
       .setType(ComponentType.PROJECT)
@@ -156,7 +164,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void do_not_add_links_on_file() {
     mockBranch(true);
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").addChildren(
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).addChildren(
       ReportComponent.builder(Component.Type.FILE, 2).setUuid("BCDE").build())
       .build());
 
@@ -179,10 +187,8 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void update_link() {
     mockBranch(true);
-    ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD")).getMainBranchComponent();
-    db.componentLinks().insertProvidedLink(project, l -> l.setType("homepage").setName("Home").setHref("http://www.sonar.org"));
-
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
+    analysisMetadataHolder.setProject(Project.fromProjectDtoWithTags(project.getProjectDto()));
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
 
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
@@ -192,7 +198,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
 
     underTest.execute(new TestComputationStepContext());
 
-    assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), "ABCD"))
+    assertThat(db.getDbClient().projectLinkDao().selectByProjectUuid(db.getSession(), project.getProjectDto().getUuid()))
       .extracting(ProjectLinkDto::getType, ProjectLinkDto::getHref)
       .containsExactlyInAnyOrder(tuple("homepage", "http://www.sonarqube.org"));
   }
@@ -200,10 +206,9 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void delete_link() {
     mockBranch(true);
-    ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD")).getMainBranchComponent();
-    db.componentLinks().insertProvidedLink(project, l -> l.setType("homepage").setName("Home").setHref("http://www.sonar.org"));
+    db.projectLinks().insertProvidedLink(project.getProjectDto(), l -> l.setType("homepage").setName("Home").setHref("http://www.sonar.org"));
 
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
 
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
@@ -218,10 +223,9 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void not_delete_custom_link() {
     mockBranch(true);
-    ComponentDto project = db.components().insertPrivateProject(p -> p.setUuid("ABCD")).getMainBranchComponent();
-    db.componentLinks().insertCustomLink(project);
+    db.projectLinks().insertCustomLink(project.getProjectDto());
 
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
 
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
@@ -236,7 +240,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
   @Test
   public void fail_when_trying_to_add_same_link_type_multiple_times() {
     mockBranch(true);
-    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").build());
+    treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.getMainBranchComponent().uuid()).build());
 
     reportReader.putComponent(ScannerReport.Component.newBuilder()
       .setRef(1)
@@ -247,7 +251,7 @@ public class PersistProjectLinksStepIT extends BaseStepTest {
 
     assertThatThrownBy(() -> underTest.execute(new TestComputationStepContext()))
       .isInstanceOf(IllegalArgumentException.class)
-      .hasMessage("Link of type 'homepage' has already been declared on component 'ABCD'");
+      .hasMessage("Link of type 'homepage' has already been declared on component '%s'".formatted(project.projectUuid()));
   }
 
   private void mockBranch(boolean isMain) {
index 117e24e288b998b4bda6efa32f49bdff88ebc70c..693621a22fffd3bd82265184b4e90d48fe51b580 100644 (file)
@@ -24,14 +24,11 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.slf4j.event.Level;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
 import org.sonar.api.testfixtures.log.LogTester;
 import org.sonar.api.utils.System2;
-import org.sonar.ce.task.projectexport.component.ComponentRepository;
 import org.sonar.ce.task.step.TestComputationStepContext;
 import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.component.ProjectLinkDto;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.project.ProjectExportMapper;
@@ -41,40 +38,29 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.assertj.core.groups.Tuple.tuple;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT;
 
 public class ExportLinksStepIT {
 
   private static final String PROJECT_UUID = "project_uuid";
-  private static final ComponentDto PROJECT = new ComponentDto()
-    // no id yet
-    .setScope(Scopes.PROJECT)
-    .setQualifier(Qualifiers.PROJECT)
-    .setKey("the_project")
-    .setName("The Project")
-    .setDescription("The project description")
-    .setEnabled(true)
-    .setUuid(PROJECT_UUID)
-    .setUuidPath(UUID_PATH_OF_ROOT)
-    .setBranchUuid(PROJECT_UUID);
+
+  private ProjectDto projectDto;
 
   @Rule
   public DbTester db = DbTester.createWithExtensionMappers(System2.INSTANCE, true, ProjectExportMapper.class);
 
-
   @Rule
   public LogTester logTester = new LogTester();
 
   private final FakeDumpWriter dumpWriter = new FakeDumpWriter();
   private final ProjectHolder projectHolder = mock(ProjectHolder.class);
   private final ExportLinksStep underTest = new ExportLinksStep(db.getDbClient(), projectHolder, dumpWriter);
-  private ProjectDto project;
 
   @Before
   public void setUp() {
     logTester.setLevel(Level.DEBUG);
-    project = db.components().insertPublicProject(PROJECT).getProjectDto();
-    when(projectHolder.projectDto()).thenReturn(project);
+    ProjectData project = db.components().insertPublicProject(PROJECT_UUID);
+    this.projectDto = project.getProjectDto();
+    when(projectHolder.projectDto()).thenReturn(projectDto);
   }
 
   @Test
@@ -87,9 +73,9 @@ public class ExportLinksStepIT {
 
   @Test
   public void export_links() {
-    ProjectLinkDto link1 = db.componentLinks().insertCustomLink(project);
-    ProjectLinkDto link2 = db.componentLinks().insertProvidedLink(project);
-    db.componentLinks().insertCustomLink(db.components().insertPrivateProject().getProjectDto());
+    ProjectLinkDto link1 = db.projectLinks().insertCustomLink(projectDto);
+    ProjectLinkDto link2 = db.projectLinks().insertProvidedLink(projectDto);
+    db.projectLinks().insertCustomLink(db.components().insertPrivateProject().getProjectDto());
 
     underTest.execute(new TestComputationStepContext());
 
@@ -103,10 +89,10 @@ public class ExportLinksStepIT {
 
   @Test
   public void throws_ISE_if_error() {
-    db.componentLinks().insertCustomLink(project);
-    db.componentLinks().insertProvidedLink(project);
-    db.componentLinks().insertProvidedLink(project);
-    db.componentLinks().insertCustomLink(db.components().insertPrivateProject().getProjectDto());
+    db.projectLinks().insertCustomLink(projectDto);
+    db.projectLinks().insertProvidedLink(projectDto);
+    db.projectLinks().insertProvidedLink(projectDto);
+    db.projectLinks().insertCustomLink(db.components().insertPrivateProject().getProjectDto());
 
     dumpWriter.failIfMoreThan(2, DumpElement.LINKS);
 
@@ -117,7 +103,7 @@ public class ExportLinksStepIT {
 
   @Test
   public void test_all_fields() {
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project, l -> l.setName("name").setHref("href").setType("type"));
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(projectDto, l -> l.setName("name").setHref("href").setType("type"));
 
     underTest.execute(new TestComputationStepContext());
 
index 9b9d055f0f1acf6d4e303a08f6cfee990ea4944d..a0f9c71c3cb44f3f5bc231279b6a79fa57825e24 100644 (file)
@@ -67,20 +67,20 @@ public class PersistProjectLinksStep implements ComputationStep {
     }
 
     try (DbSession session = dbClient.openSession(false)) {
-      Component project = treeRootHolder.getRoot();
-      ScannerReport.Component batchComponent = reportReader.readComponent(project.getReportAttributes().getRef());
-      List<ProjectLinkDto> previousLinks = dbClient.projectLinkDao().selectByProjectUuid(session, project.getUuid());
-      mergeLinks(session, project.getUuid(), batchComponent.getLinkList(), previousLinks);
+      Component rootComponent = treeRootHolder.getRoot();
+      ScannerReport.Component batchComponent = reportReader.readComponent(rootComponent.getReportAttributes().getRef());
+      List<ProjectLinkDto> previousLinks = dbClient.projectLinkDao().selectByProjectUuid(session, analysisMetadataHolder.getProject().getUuid());
+      mergeLinks(session, analysisMetadataHolder.getProject().getUuid(), batchComponent.getLinkList(), previousLinks);
       session.commit();
     }
   }
 
-  private void mergeLinks(DbSession session, String componentUuid, List<ScannerReport.ComponentLink> links, List<ProjectLinkDto> previousLinks) {
+  private void mergeLinks(DbSession session, String projectUuid, List<ScannerReport.ComponentLink> links, List<ProjectLinkDto> previousLinks) {
     Set<String> linkType = new HashSet<>();
     links.forEach(
       link -> {
         String type = convertType(link.getType());
-        checkArgument(!linkType.contains(type), "Link of type '%s' has already been declared on component '%s'", type, componentUuid);
+        checkArgument(!linkType.contains(type), "Link of type '%s' has already been declared on component '%s'", type, projectUuid);
         linkType.add(type);
 
         Optional<ProjectLinkDto> previousLink = previousLinks.stream()
@@ -93,7 +93,7 @@ public class PersistProjectLinksStep implements ComputationStep {
           dbClient.projectLinkDao().insert(session,
             new ProjectLinkDto()
               .setUuid(uuidFactory.create())
-              .setProjectUuid(componentUuid)
+              .setProjectUuid(projectUuid)
               .setType(type)
               .setHref(link.getHref()));
         }
index 466a8cc70606f93b700f3bef67d979a7ad0ceeae..f438c73ca383b3be9505117279d4a625215fd8c2 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Test;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
+import org.sonar.db.project.ProjectDto;
 
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
@@ -38,14 +39,14 @@ public class ProjectLinkDaoIT {
   private System2 system2 = new TestSystem2().setNow(NOW);
 
   @Rule
-  public DbTester db = DbTester.create(system2);
+  public DbTester db = DbTester.create(system2, true);
 
   private ProjectLinkDao underTest = db.getDbClient().projectLinkDao();
 
   @Test
   public void select_by_id() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertProvidedLink(project, c -> c
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertProvidedLink(project, c -> c
       .setUuid("ABCD")
       .setName("Home")
       .setType("homepage")
@@ -54,7 +55,7 @@ public class ProjectLinkDaoIT {
     ProjectLinkDto reloaded = underTest.selectByUuid(db.getSession(), link.getUuid());
 
     assertThat(reloaded.getUuid()).isEqualTo("ABCD");
-    assertThat(reloaded.getProjectUuid()).isEqualTo(project.uuid());
+    assertThat(reloaded.getProjectUuid()).isEqualTo(project.getUuid());
     assertThat(reloaded.getType()).isEqualTo("homepage");
     assertThat(reloaded.getName()).isEqualTo("Home");
     assertThat(reloaded.getHref()).isEqualTo("http://www.struts.org");
@@ -64,17 +65,17 @@ public class ProjectLinkDaoIT {
 
   @Test
   public void select_by_project_uuid() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link1 = db.componentLinks().insertProvidedLink(project);
-    ProjectLinkDto link2 = db.componentLinks().insertProvidedLink(project);
-    ProjectLinkDto link3 = db.componentLinks().insertProvidedLink(project);
-    ComponentDto otherProject = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto otherLink = db.componentLinks().insertProvidedLink(otherProject);
-
-    assertThat(underTest.selectByProjectUuid(db.getSession(), project.uuid()))
+    ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link1 = db.projectLinks().insertProvidedLink(project1);
+    ProjectLinkDto link2 = db.projectLinks().insertProvidedLink(project1);
+    ProjectLinkDto link3 = db.projectLinks().insertProvidedLink(project1);
+    ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto otherLink = db.projectLinks().insertProvidedLink(project2);
+
+    assertThat(underTest.selectByProjectUuid(db.getSession(), project1.getUuid()))
       .extracting(ProjectLinkDto::getUuid)
       .containsExactlyInAnyOrder(link1.getUuid(), link2.getUuid(), link3.getUuid());
-    assertThat(underTest.selectByProjectUuid(db.getSession(), otherProject.uuid()))
+    assertThat(underTest.selectByProjectUuid(db.getSession(), project2.getUuid()))
       .extracting(ProjectLinkDto::getUuid)
       .containsExactlyInAnyOrder(otherLink.getUuid());
     assertThat(underTest.selectByProjectUuid(db.getSession(), "UNKNOWN")).isEmpty();
@@ -82,16 +83,16 @@ public class ProjectLinkDaoIT {
 
   @Test
   public void select_by_project_uuids() {
-    ComponentDto project1 = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link1 = db.componentLinks().insertProvidedLink(project1);
-    ProjectLinkDto link2 = db.componentLinks().insertProvidedLink(project1);
-    ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link3 = db.componentLinks().insertProvidedLink(project2);
+    ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link1 = db.projectLinks().insertProvidedLink(project1);
+    ProjectLinkDto link2 = db.projectLinks().insertProvidedLink(project1);
+    ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link3 = db.projectLinks().insertProvidedLink(project2);
 
-    assertThat(underTest.selectByProjectUuids(db.getSession(), asList(project1.uuid(), project2.uuid())))
+    assertThat(underTest.selectByProjectUuids(db.getSession(), asList(project1.getUuid(), project2.getUuid())))
       .extracting(ProjectLinkDto::getUuid)
       .containsOnly(link1.getUuid(), link2.getUuid(), link3.getUuid());
-    assertThat(underTest.selectByProjectUuids(db.getSession(), singletonList(project1.uuid())))
+    assertThat(underTest.selectByProjectUuids(db.getSession(), singletonList(project1.getUuid())))
       .extracting(ProjectLinkDto::getUuid)
       .containsOnly(link1.getUuid(), link2.getUuid());
     assertThat(underTest.selectByProjectUuids(db.getSession(), Collections.emptyList())).isEmpty();
@@ -99,10 +100,10 @@ public class ProjectLinkDaoIT {
 
   @Test
   public void insert() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
     ProjectLinkDto link = ProjectLinkTesting.newProvidedLinkDto()
       .setUuid("ABCD")
-      .setProjectUuid(project.uuid())
+      .setProjectUuid(project.getUuid())
       .setName("Home")
       .setType("homepage")
       .setHref("http://www.struts.org")
@@ -115,7 +116,7 @@ public class ProjectLinkDaoIT {
 
     ProjectLinkDto reloaded = underTest.selectByUuid(db.getSession(), link.getUuid());
     assertThat(reloaded.getUuid()).isEqualTo("ABCD");
-    assertThat(reloaded.getProjectUuid()).isEqualTo(project.uuid());
+    assertThat(reloaded.getProjectUuid()).isEqualTo(project.getUuid());
     assertThat(reloaded.getType()).isEqualTo("homepage");
     assertThat(reloaded.getName()).isEqualTo("Home");
     assertThat(reloaded.getHref()).isEqualTo("http://www.struts.org");
@@ -125,8 +126,8 @@ public class ProjectLinkDaoIT {
 
   @Test
   public void update() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertProvidedLink(project, c -> c
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertProvidedLink(project, c -> c
       .setUuid("ABCD")
       .setType("ci")
       .setName("Gihub")
@@ -154,8 +155,8 @@ public class ProjectLinkDaoIT {
 
   @Test
   public void delete() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertProvidedLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertProvidedLink(project);
 
     underTest.delete(db.getSession(), link.getUuid());
     db.getSession().commit();
index 31bbc77973f51c08cd5c18f3898c4188ca6e43d0..1957e7e368a7c3246567a9332d791060cac8ddb5 100644 (file)
@@ -39,6 +39,7 @@ import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
+import org.sonar.db.Pagination;
 import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.audit.NoOpAuditPersister;
 import org.sonar.db.component.BranchDto;
@@ -51,6 +52,7 @@ import org.sonar.db.qualityprofile.QProfileDto;
 import static java.util.Collections.emptySet;
 import static org.apache.commons.lang.math.RandomUtils.nextInt;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.in;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
@@ -344,6 +346,30 @@ public class ProjectDaoIT {
     assertThat(projectUuids).containsExactlyInAnyOrder(project.projectUuid(), project2.projectUuid());
   }
 
+  // methodName_when<conditionInCamelCase>_should<assertionInCamelCase>
+  @Test
+  public void selectByUuids_whenUuidsAreEmptyWithPagination_shouldReturnEmptyList() {
+    db.components().insertPublicProject();
+
+    List<ProjectDto> projectDtos = projectDao.selectByUuids(db.getSession(), emptySet(), Pagination.forPage(1).andSize(1));
+
+    assertThat(projectDtos).isEmpty();
+  }
+
+  @Test
+  public void selectByUuids_whenPagination_shouldReturnSubSetOfPagination() {
+    Set<String> projectUuids = new HashSet<>();
+    for (int i = 0; i < 5; i++) {
+      final String name = "Project_" + i;
+      String projectUuid = db.components().insertPublicProject(c -> c.setName(name)).projectUuid();
+      projectUuids.add(projectUuid);
+    }
+
+    List<ProjectDto> projectDtos = projectDao.selectByUuids(db.getSession(), projectUuids, Pagination.forPage(2).andSize(2));
+
+    assertThat(projectDtos).extracting(ProjectDto::getName).containsOnly("Project_2", "Project_3");
+  }
+
   private void insertDefaultQualityProfile(String language) {
     QProfileDto profile = db.qualityProfiles().insert(qp -> qp.setIsBuiltIn(true).setLanguage(language));
     db.qualityProfiles().setAsDefault(profile);
index fda4a64bcb87525ffee4895429d8c9e09d5599f1..94684662079985b2864d7d6701bcb39113e8faa0 100644 (file)
 package org.sonar.db.user;
 
 import java.util.List;
+import java.util.Set;
 import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.util.Uuids;
@@ -37,6 +39,8 @@ import static org.sonar.db.permission.GlobalPermission.ADMINISTER;
 
 public class RoleDaoIT {
 
+  private static final Set<String> PROJECT_QUALIFIER = Set.of(Qualifiers.PROJECT);
+
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
 
@@ -58,18 +62,18 @@ public class RoleDaoIT {
 
   @Test
   public void selectComponentUuidsByPermissionAndUserId_throws_IAR_if_permission_USER_is_specified() {
-    expectUnsupportedUserAndCodeViewerPermission(() -> underTest.selectEntityUuidsByPermissionAndUserUuid(dbSession, UserRole.USER, Uuids.createFast()));
+    expectUnsupportedUserAndCodeViewerPermission(() -> underTest.selectEntityUuidsByPermissionAndUserUuidAndQualifier(dbSession, UserRole.USER, Uuids.createFast(), PROJECT_QUALIFIER));
   }
 
   @Test
   public void selectComponentUuidsByPermissionAndUserId_throws_IAR_if_permission_CODEVIEWER_is_specified() {
-    expectUnsupportedUserAndCodeViewerPermission(() -> underTest.selectEntityUuidsByPermissionAndUserUuid(dbSession, UserRole.CODEVIEWER, Uuids.createFast()));
+    expectUnsupportedUserAndCodeViewerPermission(() -> underTest.selectEntityUuidsByPermissionAndUserUuidAndQualifier(dbSession, UserRole.CODEVIEWER, Uuids.createFast(), PROJECT_QUALIFIER));
   }
 
   private void expectUnsupportedUserAndCodeViewerPermission(ThrowingCallable callback) {
     assertThatThrownBy(callback)
       .isInstanceOf(IllegalArgumentException.class)
-      .hasMessage("Permissions [user, codeviewer] are not supported by selectEntityUuidsByPermissionAndUserUuid");
+      .hasMessage("Permissions [user, codeviewer] are not supported by selectEntityUuidsByPermissionAndUserUuidAndQualifier");
   }
 
   @Test
@@ -83,7 +87,7 @@ public class RoleDaoIT {
     // project permission on another permission - not returned
     db.users().insertProjectPermissionOnUser(user1, UserRole.ISSUE_ADMIN, project1);
 
-    List<String> entityUuids = underTest.selectEntityUuidsByPermissionAndUserUuid(dbSession, UserRole.ADMIN, user1.getUuid());
+    List<String> entityUuids = underTest.selectEntityUuidsByPermissionAndUserUuidAndQualifier(dbSession, UserRole.ADMIN, user1.getUuid(), PROJECT_QUALIFIER);
 
     assertThat(entityUuids).containsExactly(project1.uuid(), project2.uuid());
   }
@@ -104,7 +108,7 @@ public class RoleDaoIT {
     // project permission on another permission - not returned
     db.users().insertProjectPermissionOnGroup(group1, UserRole.ISSUE_ADMIN, project1);
 
-    List<String> result = underTest.selectEntityUuidsByPermissionAndUserUuid(dbSession, UserRole.ADMIN, user1.getUuid());
+    List<String> result = underTest.selectEntityUuidsByPermissionAndUserUuidAndQualifier(dbSession, UserRole.ADMIN, user1.getUuid(), PROJECT_QUALIFIER);
 
     assertThat(result).containsExactly(project1.uuid(), project2.uuid());
   }
@@ -135,4 +139,6 @@ public class RoleDaoIT {
     assertThat(db.getDbClient().groupPermissionDao().selectGlobalPermissionsOfGroup(db.getSession(), null)).containsOnly("scan",
       "provisioning");
   }
+
+  // TODO : add test for qualifier method.
 }
index 44ef0ff0e8b77fba57e804bbffd5d5b320a6a99f..474712584093c8dfe170edddc8158ff09f412da0 100644 (file)
@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
 import org.sonar.api.utils.System2;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
+import org.sonar.db.Pagination;
 import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.audit.model.ComponentNewValue;
 
@@ -106,6 +107,13 @@ public class ProjectDao implements Dao {
     return executeLargeInputs(uuids, partition -> mapper(session).selectByUuids(partition));
   }
 
+  public List<ProjectDto> selectByUuids(DbSession session, Set<String> uuids, Pagination pagination) {
+    if (uuids.isEmpty()) {
+      return emptyList();
+    }
+    return mapper(session).selectByUuidsWithPagination(uuids, pagination);
+  }
+
   public void updateVisibility(DbSession session, String uuid, boolean isPrivate) {
     mapper(session).updateVisibility(uuid, isPrivate, system2.now());
   }
index d778d860e426ce9478e846b5fde359668b3bec2a..e189566d7bde9f4e10808eaa59d8ea96970c0a9d 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.apache.ibatis.annotations.Param;
+import org.sonar.db.Pagination;
 
 public interface ProjectMapper {
 
@@ -46,6 +47,8 @@ public interface ProjectMapper {
 
   List<ProjectDto> selectByUuids(@Param("uuids") Collection<String> uuids);
 
+  List<ProjectDto> selectByUuidsWithPagination(@Param("uuids") Collection<String> uuids, @Param("pagination") Pagination pagination);
+
   List<ProjectDto> selectAll();
 
   void updateTags(ProjectDto project);
index afea419829197915d10460584534988a5e5f16ab..b5feddc48001d64025b6697ad82860aa8421ff24 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.db.user;
 
 import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import org.sonar.api.web.UserRole;
@@ -40,11 +41,11 @@ public class RoleDao implements Dao {
    * @throws IllegalArgumentException this method does not support permissions {@link UserRole#USER user} nor
    *         {@link UserRole#CODEVIEWER codeviewer} because it does not support public root components.
    */
-  public List<String> selectEntityUuidsByPermissionAndUserUuid(DbSession dbSession, String permission, String userUuid) {
+  public List<String> selectEntityUuidsByPermissionAndUserUuidAndQualifier(DbSession dbSession, String permission, String userUuid, Collection<String> qualifiers) {
     checkArgument(
       !UNSUPPORTED_PROJECT_PERMISSIONS.contains(permission),
-      "Permissions %s are not supported by selectEntityUuidsByPermissionAndUserUuid", UNSUPPORTED_PROJECT_PERMISSIONS);
-    return mapper(dbSession).selectEntityUuidsByPermissionAndUserUuid(permission, userUuid);
+      "Permissions %s are not supported by selectEntityUuidsByPermissionAndUserUuidAndQualifier", UNSUPPORTED_PROJECT_PERMISSIONS);
+    return mapper(dbSession).selectEntityUuidsByPermissionAndUserUuidAndQualifier(permission, userUuid, qualifiers);
   }
 
   public void deleteGroupRolesByGroupUuid(DbSession session, String groupUuid) {
index 722a79bd40c0656e3570f577b028de1638b061cf..ccbb3b8b6e9388c78bd29305540792279c2282a6 100644 (file)
  */
 package org.sonar.db.user;
 
+import java.util.Collection;
 import java.util.List;
 import org.apache.ibatis.annotations.Param;
 
 public interface RoleMapper {
 
-  List<String> selectEntityUuidsByPermissionAndUserUuid(@Param("permission") String permission, @Param("userUuid") String userUuid);
+  List<String> selectEntityUuidsByPermissionAndUserUuidAndQualifier(@Param("permission") String permission,
+    @Param("userUuid") String userUuid, @Param("qualifiers") Collection<String> qualifiers);
 
   void deleteGroupRolesByGroupUuid(String groupUuid);
 
index f8a5d2ea185433e4b1a908a2ee0e004233c46092..362f33aa3c62d7ff9db8f5cff5ef41a2e02be88b 100644 (file)
       </foreach>
   </select>
 
+    <select id="selectByUuidsWithPagination" resultType="Project">
+    select
+      <include refid="projectColumns"/>
+    from projects p
+    where
+      p.uuid in
+      <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">
+        #{uuid,jdbcType=VARCHAR}
+      </foreach>
+      order by p.name, uuid desc
+      offset (#{pagination.startRowNumber,jdbcType=INTEGER}-1) rows fetch next #{pagination.pageSize,jdbcType=INTEGER} rows only
+  </select>
+
   <select id="selectProjectsByKeys" resultType="Project">
     select
       <include refid="projectColumns"/>
index a70f2b509e18a9f73a066137eff820eb8092d03f..9bf5096fc86c1e587793e188acde09b2ff2bf89a 100644 (file)
@@ -3,28 +3,36 @@
 
 <mapper namespace="org.sonar.db.user.RoleMapper">
 
-  <select id="selectEntityUuidsByPermissionAndUserUuid" parameterType="map" resultType="String">
-    select
-      ur.entity_uuid
-    from
-      user_roles ur
-    where
-      ur.user_uuid = #{userUuid,jdbcType=VARCHAR}
-      and ur.role = #{permission,jdbcType=VARCHAR}
-      and ur.entity_uuid is not null
-    union
-    select
-      gr.entity_uuid
-    from
-      group_roles gr
-    inner join groups_users gu on
-      gr.group_uuid=gu.group_uuid
-    where
-      gr.role = #{permission,jdbcType=VARCHAR}
-      and gr.entity_uuid is not null
-      and gu.user_uuid=#{userUuid,jdbcType=VARCHAR}
-    order by
-      entity_uuid
+  <select id="selectEntityUuidsByPermissionAndUserUuidAndQualifier" parameterType="map" resultType="String">
+    select entity.uuid
+    from (select
+        ur.entity_uuid
+      from
+        user_roles ur
+      where
+        ur.user_uuid = #{userUuid,jdbcType=VARCHAR}
+        and ur.role = #{permission,jdbcType=VARCHAR}
+        and ur.entity_uuid is not null
+      union
+      select
+        gr.entity_uuid
+      from
+        group_roles gr
+      inner join groups_users gu on
+        gr.group_uuid=gu.group_uuid
+      where
+        gr.role = #{permission,jdbcType=VARCHAR}
+        and gr.entity_uuid is not null
+        and gu.user_uuid=#{userUuid,jdbcType=VARCHAR} ) permissions
+    inner join
+    ( select uuid, name from (<include refid="org.sonar.db.entity.EntityMapper.selectAll"/>) e
+      where e.qualifier  in
+        <foreach collection="qualifiers" open="(" close=")" item="uuid" separator=",">
+          #{uuid,jdbcType=VARCHAR}
+        </foreach>
+    ) entity
+    on permissions.entity_uuid = entity.uuid
+    order by entity.name
   </select>
 
   <delete id="deleteGroupRolesByGroupUuid" parameterType="String">
index 0ffa35654694a592de560d62fd93be2d7933185a..6a29d3cdd3f30fc8f462a192eddeaee3cc74bae6 100644 (file)
@@ -69,7 +69,7 @@ public class DbTester extends AbstractDbTester<TestDbImpl> {
   private DbSession session = null;
   private final UserDbTester userTester;
   private final ComponentDbTester componentTester;
-  private final ProjectLinkDbTester componentLinkTester;
+  private final ProjectLinkDbTester projectLinkTester;
   private final FavoriteDbTester favoriteTester;
   private final EventDbTester eventTester;
   private final PermissionTemplateDbTester permissionTemplateTester;
@@ -98,7 +98,7 @@ public class DbTester extends AbstractDbTester<TestDbImpl> {
     initDbClient();
     this.userTester = new UserDbTester(this);
     this.componentTester = new ComponentDbTester(this, useDifferentProjectUuids);
-    this.componentLinkTester = new ProjectLinkDbTester(this);
+    this.projectLinkTester = new ProjectLinkDbTester(this);
     this.favoriteTester = new FavoriteDbTester(this);
     this.eventTester = new EventDbTester(this);
     this.permissionTemplateTester = new PermissionTemplateDbTester(this);
@@ -193,8 +193,8 @@ public class DbTester extends AbstractDbTester<TestDbImpl> {
     return componentTester;
   }
 
-  public ProjectLinkDbTester componentLinks() {
-    return componentLinkTester;
+  public ProjectLinkDbTester projectLinks() {
+    return projectLinkTester;
   }
 
   public FavoriteDbTester favorites() {
index 1e1542aeb8e435386cf3702c358cf4b3132277e0..46114943590c00c9ebd6878a332526844d991e9d 100644 (file)
@@ -39,25 +39,7 @@ public class ProjectLinkDbTester {
     this.dbClient = db.getDbClient();
     this.dbSession = db.getSession();
   }
-
-  @SafeVarargs
-  public final ProjectLinkDto insertProvidedLink(ComponentDto project, Consumer<ProjectLinkDto>... dtoPopulators) {
-    return insertLink(project, newProvidedLinkDto(), dtoPopulators);
-  }
-
-  @SafeVarargs
-  public final ProjectLinkDto insertCustomLink(ComponentDto project, Consumer<ProjectLinkDto>... dtoPopulators) {
-    return insertLink(project, newCustomLinkDto(), dtoPopulators);
-  }
-
-  @SafeVarargs
-  private final ProjectLinkDto insertLink(ComponentDto project, ProjectLinkDto componentLink, Consumer<ProjectLinkDto>... dtoPopulators) {
-    Arrays.stream(dtoPopulators).forEach(dtoPopulator -> dtoPopulator.accept(componentLink));
-    dbClient.projectLinkDao().insert(dbSession, componentLink.setProjectUuid(project.uuid()));
-    db.commit();
-    return componentLink;
-  }
-
+  
   @SafeVarargs
   public final ProjectLinkDto insertProvidedLink(ProjectDto project, Consumer<ProjectLinkDto>... dtoPopulators) {
     return insertLink(project, newProvidedLinkDto(), dtoPopulators);
index 5c0e9f886841fe3a2aa10d562ca3da8e5803b4ca..2abe6aae2046da7660d8451a9e6f2b35ec504116 100644 (file)
@@ -33,10 +33,13 @@ import org.sonar.core.util.Uuids;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.component.ProjectLinkDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.portfolio.PortfolioDto;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.UnauthorizedException;
@@ -48,7 +51,6 @@ import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse.Project;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
-import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
 import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
 import static org.sonar.db.metric.MetricTesting.newMetricDto;
@@ -60,7 +62,7 @@ public class SearchMyProjectsActionIT {
   @Rule
   public final UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
-  public final DbTester db = DbTester.create(System2.INSTANCE);
+  public final DbTester db = DbTester.create(System2.INSTANCE, true);
 
   private final DbClient dbClient = db.getDbClient();
   private final DbSession dbSession = db.getSession();
@@ -80,18 +82,18 @@ public class SearchMyProjectsActionIT {
 
   @Test
   public void search_json_example() {
-    ComponentDto jdk7 = insertJdk7();
-    ComponentDto cLang = insertClang();
-    db.componentLinks().insertProvidedLink(jdk7, l -> l.setHref("http://www.oracle.com").setType(ProjectLinkDto.TYPE_HOME_PAGE).setName("Home"));
-    db.componentLinks().insertProvidedLink(jdk7, l -> l.setHref("http://download.java.net/openjdk/jdk8/").setType(ProjectLinkDto.TYPE_SOURCES).setName("Sources"));
+    ProjectData jdk7 = insertJdk7();
+    ProjectData cLang = insertClang();
+    db.projectLinks().insertProvidedLink(jdk7.getProjectDto(), l -> l.setHref("http://www.oracle.com").setType(ProjectLinkDto.TYPE_HOME_PAGE).setName("Home"));
+    db.projectLinks().insertProvidedLink(jdk7.getProjectDto(), l -> l.setHref("http://download.java.net/openjdk/jdk8/").setType(ProjectLinkDto.TYPE_SOURCES).setName("Sources"));
     long oneTime = DateUtils.parseDateTime("2016-06-10T13:17:53+0000").getTime();
     long anotherTime = DateUtils.parseDateTime("2016-06-11T14:25:53+0000").getTime();
-    SnapshotDto jdk7Snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(jdk7).setCreatedAt(oneTime));
-    SnapshotDto cLangSnapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(cLang).setCreatedAt(anotherTime));
-    dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(jdk7, alertStatusMetric).setData(Level.ERROR.name()));
-    dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(cLang, alertStatusMetric).setData(Level.OK.name()));
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7);
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, cLang);
+    SnapshotDto jdk7Snapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(jdk7.getMainBranchDto()).setCreatedAt(oneTime));
+    SnapshotDto cLangSnapshot = dbClient.snapshotDao().insert(dbSession, newAnalysis(cLang.getMainBranchDto()).setCreatedAt(anotherTime));
+    dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(jdk7.getMainBranchDto(), alertStatusMetric).setData(Level.ERROR.name()));
+    dbClient.liveMeasureDao().insert(dbSession, newLiveMeasure(cLang.getMainBranchDto(), alertStatusMetric).setData(Level.OK.name()));
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7.getProjectDto());
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, cLang.getProjectDto());
     db.commit();
     System.setProperty("user.timezone", "UTC");
 
@@ -102,11 +104,11 @@ public class SearchMyProjectsActionIT {
 
   @Test
   public void return_only_current_user_projects() {
-    ComponentDto jdk7 = insertJdk7();
-    ComponentDto cLang = insertClang();
+    ProjectData jdk7 = insertJdk7();
+    ProjectData cLang = insertClang();
     UserDto anotherUser = db.users().insertUser(newUserDto());
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7);
-    db.users().insertProjectPermissionOnUser(anotherUser, UserRole.ADMIN, cLang);
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7.getProjectDto());
+    db.users().insertProjectPermissionOnUser(anotherUser, UserRole.ADMIN, cLang.getProjectDto());
 
     SearchMyProjectsWsResponse result = callWs();
 
@@ -144,8 +146,8 @@ public class SearchMyProjectsActionIT {
   public void paginate_projects() {
     for (int i = 0; i < 10; i++) {
       int j = i;
-      ComponentDto project = db.components().insertPrivateProject(p -> p.setName("project-" + j)).getMainBranchComponent();
-      db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, project);
+      ProjectData project = db.components().insertPrivateProject(p -> p.setName("project-" + j));
+      db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, project.getProjectDto());
     }
 
     SearchMyProjectsWsResponse result = ws.newRequest()
@@ -153,17 +155,17 @@ public class SearchMyProjectsActionIT {
       .setParam(Param.PAGE_SIZE, "3")
       .executeProtobuf(SearchMyProjectsWsResponse.class);
 
-    assertThat(result.getProjectsCount()).isEqualTo(3);
     assertThat(result.getProjectsList()).extracting(Project::getName).containsExactly("project-3", "project-4", "project-5");
+    assertThat(result.getProjectsCount()).isEqualTo(3);
   }
 
   @Test
   public void return_only_projects_when_user_is_admin() {
-    ComponentDto jdk7 = insertJdk7();
-    ComponentDto clang = insertClang();
+    ProjectData jdk7 = insertJdk7();
+    ProjectData clang = insertClang();
 
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7);
-    db.users().insertProjectPermissionOnUser(user, UserRole.ISSUE_ADMIN, clang);
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7.getProjectDto());
+    db.users().insertProjectPermissionOnUser(user, UserRole.ISSUE_ADMIN, clang.getProjectDto());
 
     SearchMyProjectsWsResponse result = callWs();
 
@@ -172,10 +174,10 @@ public class SearchMyProjectsActionIT {
 
   @Test
   public void does_not_return_views() {
-    ComponentDto jdk7 = insertJdk7();
-    ComponentDto portfolio = insertPortfolio();
+    ProjectData jdk7 = insertJdk7();
+    PortfolioDto portfolio = insertPortfolio();
 
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7);
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7.getProjectDto());
     db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, portfolio);
 
     SearchMyProjectsWsResponse result = callWs();
@@ -185,27 +187,27 @@ public class SearchMyProjectsActionIT {
 
   @Test
   public void does_not_return_branches() {
-    ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
-    ComponentDto branch = db.components().insertProjectBranch(project);
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, project);
+    ProjectData project = db.components().insertPublicProject();
+    BranchDto branch = db.components().insertProjectBranch(project.getProjectDto());
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, project.getProjectDto());
 
     SearchMyProjectsWsResponse result = callWs();
 
     assertThat(result.getProjectsList())
       .extracting(Project::getKey)
-      .containsExactlyInAnyOrder(project.getKey());
+      .containsExactlyInAnyOrder(project.getProjectDto().getKey());
   }
 
   @Test
   public void admin_via_groups() {
-    ComponentDto jdk7 = insertJdk7();
-    ComponentDto cLang = insertClang();
+    ProjectData jdk7 = insertJdk7();
+    ProjectData cLang = insertClang();
 
     GroupDto group = db.users().insertGroup();
     db.users().insertMember(group, user);
 
-    db.users().insertProjectPermissionOnGroup(group, UserRole.ADMIN, jdk7);
-    db.users().insertProjectPermissionOnGroup(group, UserRole.USER, cLang);
+    db.users().insertEntityPermissionOnGroup(group, UserRole.ADMIN, jdk7.getProjectDto());
+    db.users().insertEntityPermissionOnGroup(group, UserRole.USER, cLang.getProjectDto());
 
     SearchMyProjectsWsResponse result = callWs();
 
@@ -214,18 +216,18 @@ public class SearchMyProjectsActionIT {
 
   @Test
   public void admin_via_groups_and_users() {
-    ComponentDto jdk7 = insertJdk7();
-    ComponentDto cLang = insertClang();
-    ComponentDto sonarqube = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectData jdk7 = insertJdk7();
+    ProjectData cLang = insertClang();
+    ProjectData sonarqube = db.components().insertPrivateProject();
 
     GroupDto group = db.users().insertGroup();
     db.users().insertMember(group, user);
 
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7);
-    db.users().insertProjectPermissionOnGroup(group, UserRole.ADMIN, cLang);
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, jdk7.getProjectDto());
+    db.users().insertEntityPermissionOnGroup(group, UserRole.ADMIN, cLang.getProjectDto());
     // admin via group and user
-    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, sonarqube);
-    db.users().insertProjectPermissionOnGroup(group, UserRole.ADMIN, sonarqube);
+    db.users().insertProjectPermissionOnUser(user, UserRole.ADMIN, sonarqube.getProjectDto());
+    db.users().insertEntityPermissionOnGroup(group, UserRole.ADMIN, sonarqube.getProjectDto());
 
     SearchMyProjectsWsResponse result = callWs();
 
@@ -246,22 +248,22 @@ public class SearchMyProjectsActionIT {
       .isInstanceOf(UnauthorizedException.class);
   }
 
-  private ComponentDto insertClang() {
+  private ProjectData insertClang() {
     return db.components().insertPrivateProject(Uuids.UUID_EXAMPLE_01, p -> p
       .setName("Clang")
-      .setKey("clang")).getMainBranchComponent();
+      .setKey("clang"));
   }
 
-  private ComponentDto insertJdk7() {
+  private ProjectData insertJdk7() {
     return db.components().insertPrivateProject(Uuids.UUID_EXAMPLE_02, p -> p
       .setName("JDK 7")
       .setKey("net.java.openjdk:jdk7")
-      .setDescription("JDK")).getMainBranchComponent();
+      .setDescription("JDK"));
   }
 
-  private ComponentDto insertPortfolio() {
+  private PortfolioDto insertPortfolio() {
     String uuid = "752d8bfd-420c-4a83-a4e5-8ab19b13c8fc";
-    return db.components().insertPublicPortfolio(p -> p.setUuid("752d8bfd-420c-4a83-a4e5-8ab19b13c8fc")
+    return db.components().insertPublicPortfolioDto(p -> p.setUuid("752d8bfd-420c-4a83-a4e5-8ab19b13c8fc")
         .setName("Java")
         .setKey("Java"),
       p -> p.setRootUuid(uuid));
index 3c1fbfb4091c94969813a02989b7ee9f13478f71..0f3637ac02326ca3533a56b62736dc414c4f86e4 100644 (file)
@@ -26,8 +26,8 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ProjectLinkDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
@@ -45,7 +45,7 @@ public class DeleteActionIT {
   @Rule
   public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create(System2.INSTANCE, true);
 
   private DbClient dbClient = db.getDbClient();
   private DbSession dbSession = db.getSession();
@@ -54,8 +54,8 @@ public class DeleteActionIT {
 
   @Test
   public void no_response() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     logInAsProjectAdministrator(project);
 
     TestResponse response = deleteLink(link);
@@ -66,8 +66,8 @@ public class DeleteActionIT {
 
   @Test
   public void remove_custom_link() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     logInAsProjectAdministrator(project);
 
     deleteLink(link);
@@ -77,10 +77,10 @@ public class DeleteActionIT {
 
   @Test
   public void keep_links_of_another_project() {
-    ComponentDto project1 = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto customLink1 = db.componentLinks().insertCustomLink(project1);
-    ProjectLinkDto customLink2 = db.componentLinks().insertCustomLink(project2);
+    ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
+    ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto customLink1 = db.projectLinks().insertCustomLink(project1);
+    ProjectLinkDto customLink2 = db.projectLinks().insertCustomLink(project2);
     userSession.logIn().addProjectPermission(ADMIN, project1, project2);
 
     deleteLink(customLink1);
@@ -91,8 +91,8 @@ public class DeleteActionIT {
 
   @Test
   public void fail_when_delete_provided_link() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertProvidedLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertProvidedLink(project);
     logInAsProjectAdministrator(project);
 
     assertThatThrownBy(() -> deleteLink(link))
@@ -106,13 +106,13 @@ public class DeleteActionIT {
       .setMethod("POST")
       .setParam(PARAM_ID, "UNKNOWN")
       .execute())
-      .isInstanceOf(NotFoundException.class);
+        .isInstanceOf(NotFoundException.class);
   }
 
   @Test
   public void fail_if_anonymous() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     userSession.anonymous();
 
     assertThatThrownBy(() -> deleteLink(link))
@@ -121,8 +121,8 @@ public class DeleteActionIT {
 
   @Test
   public void fail_if_not_project_admin() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     userSession.logIn();
 
     assertThatThrownBy(() -> deleteLink(link))
@@ -154,7 +154,7 @@ public class DeleteActionIT {
     assertThat(dbClient.projectLinkDao().selectByUuid(dbSession, uuid)).isNotNull();
   }
 
-  private void logInAsProjectAdministrator(ComponentDto project) {
+  private void logInAsProjectAdministrator(ProjectDto project) {
     userSession.logIn().addProjectPermission(ADMIN, project);
   }
 }
index 73a10a7f898216b7021687f18607c710c4ea80cb..3a6a3971a7fdbe11ad41b48ec6e674c7357fa6d9 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.component.ProjectLinkDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.component.TestComponentFinder;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
@@ -51,7 +52,7 @@ public class SearchActionIT {
   @Rule
   public UserSessionRule userSession = UserSessionRule.standalone();
   @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create(System2.INSTANCE, true);
 
   private DbClient dbClient = db.getDbClient();
 
@@ -59,9 +60,9 @@ public class SearchActionIT {
 
   @Test
   public void example() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    db.componentLinks().insertProvidedLink(project, l -> l.setUuid("1").setType("homepage").setName("Homepage").setHref("http://example.org"));
-    db.componentLinks().insertCustomLink(project, l -> l.setUuid("2").setType("custom").setName("Custom").setHref("http://example.org/custom"));
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    db.projectLinks().insertProvidedLink(project, l -> l.setUuid("1").setType("homepage").setName("Homepage").setHref("http://example.org"));
+    db.projectLinks().insertCustomLink(project, l -> l.setUuid("2").setType("custom").setName("Custom").setHref("http://example.org/custom"));
     logInAsProjectAdministrator(project);
 
     String result = ws.newRequest()
@@ -73,11 +74,11 @@ public class SearchActionIT {
 
   @Test
   public void request_by_project_id() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     logInAsProjectAdministrator(project);
 
-    SearchWsResponse response = callByUuid(project.uuid());
+    SearchWsResponse response = callByUuid(project.getUuid());
 
     assertThat(response.getLinksList())
       .extracting(Link::getId, Link::getName)
@@ -86,8 +87,8 @@ public class SearchActionIT {
 
   @Test
   public void request_by_project_key() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     logInAsProjectAdministrator(project);
 
     SearchWsResponse response = callByKey(project.getKey());
@@ -99,9 +100,9 @@ public class SearchActionIT {
 
   @Test
   public void response_fields() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto homepageLink = db.componentLinks().insertProvidedLink(project);
-    ProjectLinkDto customLink = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto homepageLink = db.projectLinks().insertProvidedLink(project);
+    ProjectLinkDto customLink = db.projectLinks().insertCustomLink(project);
     logInAsProjectAdministrator(project);
 
     SearchWsResponse response = callByKey(project.getKey());
@@ -114,10 +115,10 @@ public class SearchActionIT {
 
   @Test
   public void several_projects() {
-    ComponentDto project1 = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link1 = db.componentLinks().insertCustomLink(project1);
-    ProjectLinkDto link2 = db.componentLinks().insertCustomLink(project2);
+    ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
+    ProjectDto project2 = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link1 = db.projectLinks().insertCustomLink(project1);
+    ProjectLinkDto link2 = db.projectLinks().insertCustomLink(project2);
     userSession.addProjectPermission(USER, project1);
     userSession.addProjectPermission(USER, project2);
 
@@ -130,8 +131,8 @@ public class SearchActionIT {
 
   @Test
   public void request_does_not_fail_when_link_has_no_name() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertProvidedLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertProvidedLink(project);
     logInAsProjectAdministrator(project);
 
     SearchWsResponse response = callByKey(project.getKey());
@@ -143,8 +144,8 @@ public class SearchActionIT {
 
   @Test
   public void project_administrator_can_search_for_links() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     logInAsProjectAdministrator(project);
 
     SearchWsResponse response = callByKey(project.getKey());
@@ -156,8 +157,8 @@ public class SearchActionIT {
 
   @Test
   public void project_user_can_search_for_links() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ProjectLinkDto link = db.componentLinks().insertCustomLink(project);
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
     userSession.logIn().addProjectPermission(USER, project);
 
     SearchWsResponse response = callByKey(project.getKey());
@@ -207,12 +208,12 @@ public class SearchActionIT {
 
   @Test
   public void fail_when_both_id_and_key_are_provided() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
     logInAsProjectAdministrator(project);
 
     assertThatThrownBy(() -> ws.newRequest()
       .setParam(PARAM_PROJECT_KEY, project.getKey())
-      .setParam(PARAM_PROJECT_ID, project.uuid())
+      .setParam(PARAM_PROJECT_ID, project.getUuid())
       .execute())
       .isInstanceOf(IllegalArgumentException.class);
   }
@@ -263,7 +264,7 @@ public class SearchActionIT {
       .executeProtobuf(SearchWsResponse.class);
   }
 
-  private void logInAsProjectAdministrator(ComponentDto project) {
+  private void logInAsProjectAdministrator(ProjectDto project) {
     userSession.logIn().addProjectPermission(ADMIN, project);
   }
 
index 5aa2b9bd038b3aa35f2fa2cd79262a1c42b3bfd1..520e24a922857dee42d69e0aa17616b67d3dcb6c 100644 (file)
 package org.sonar.server.project.ws;
 
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
 import java.util.List;
+import java.util.Set;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.sonar.api.measures.CoreMetrics;
@@ -35,11 +36,12 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.DatabaseUtils;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentQuery;
+import org.sonar.db.Pagination;
+import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ProjectLinkDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.LiveMeasureDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.user.UserSession;
 import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse;
 import org.sonarqube.ws.Projects.SearchMyProjectsWsResponse.Link;
@@ -51,7 +53,6 @@ import static java.util.Collections.singletonList;
 import static java.util.Objects.requireNonNull;
 import static java.util.Optional.ofNullable;
 import static org.sonar.api.utils.DateUtils.formatDateTime;
-import static org.sonar.api.utils.Paging.offset;
 import static org.sonar.server.project.ws.SearchMyProjectsData.builder;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 
@@ -97,6 +98,7 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
     SearchMyProjectsWsResponse.Builder response = SearchMyProjectsWsResponse.newBuilder();
 
     ProjectDtoToWs projectDtoToWs = new ProjectDtoToWs(data);
+
     data.projects().stream()
       .map(projectDtoToWs)
       .forEach(response::addProjects);
@@ -121,7 +123,7 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
       .build();
   }
 
-  private static class ProjectDtoToWs implements Function<ComponentDto, Project> {
+  private static class ProjectDtoToWs implements Function<ProjectDto, Project> {
     private final SearchMyProjectsData data;
 
     private ProjectDtoToWs(SearchMyProjectsData data) {
@@ -129,21 +131,23 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
     }
 
     @Override
-    public Project apply(ComponentDto dto) {
+    public Project apply(ProjectDto dto) {
       Project.Builder project = Project.newBuilder();
+
       project
         .setKey(dto.getKey())
-        .setName(dto.name());
-      data.lastSnapshot(dto.uuid()).ifPresent(s -> {
+        .setName(dto.getName());
+      ofNullable(emptyToNull(dto.getDescription())).ifPresent(project::setDescription);
+      data.projectLinksFor(dto.getUuid()).stream()
+        .map(ProjectLinkDtoToWs.INSTANCE)
+        .forEach(project::addLinks);
+
+      String mainBranchUuid = data.mainBranchUuidForProjectUuid(dto.getUuid());
+      data.lastSnapshot(mainBranchUuid).ifPresent(s -> {
         project.setLastAnalysisDate(formatDateTime(s.getCreatedAt()));
         ofNullable(s.getRevision()).ifPresent(project::setRevision);
       });
-      data.qualityGateStatusFor(dto.uuid()).ifPresent(project::setQualityGate);
-      ofNullable(emptyToNull(dto.description())).ifPresent(project::setDescription);
-
-      data.projectLinksFor(dto.uuid()).stream()
-        .map(ProjectLinkDtoToWs.INSTANCE)
-        .forEach(project::addLinks);
+      data.qualityGateStatusFor(mainBranchUuid).ifPresent(project::setQualityGate);
 
       return project.build();
     }
@@ -171,14 +175,22 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
   private SearchMyProjectsData load(DbSession dbSession, SearchMyProjectsRequest request) {
     SearchMyProjectsData.Builder data = builder();
     ProjectsResult searchResult = searchProjects(dbSession, request);
-    List<ComponentDto> projects = searchResult.projects;
-    List<String> projectUuids = Lists.transform(projects, ComponentDto::branchUuid);
+    List<ProjectDto> projects = searchResult.projects;
+
+    List<String> projectUuids = projects.stream().map(ProjectDto::getUuid).toList();
     List<ProjectLinkDto> projectLinks = dbClient.projectLinkDao().selectByProjectUuids(dbSession, projectUuids);
-    List<SnapshotDto> snapshots = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids);
+
+    List<BranchDto> branches = searchResult.branches;
+
+    Set<String> mainBranchUuids = branches.stream().map(BranchDto::getUuid).collect(Collectors.toSet());
+    List<SnapshotDto> snapshots = dbClient.snapshotDao()
+      .selectLastAnalysesByRootComponentUuids(dbSession, mainBranchUuids);
     List<LiveMeasureDto> qualityGates = dbClient.liveMeasureDao()
-      .selectByComponentUuidsAndMetricKeys(dbSession, projectUuids, singletonList(CoreMetrics.ALERT_STATUS_KEY));
+      .selectByComponentUuidsAndMetricKeys(dbSession, mainBranchUuids, singletonList(CoreMetrics.ALERT_STATUS_KEY));
 
-    data.setProjects(projects)
+    data
+      .setProjects(projects)
+      .setBranches(searchResult.branches)
       .setProjectLinks(projectLinks)
       .setSnapshots(snapshots)
       .setQualityGates(qualityGates)
@@ -190,25 +202,35 @@ public class SearchMyProjectsAction implements ProjectsWsAction {
   private ProjectsResult searchProjects(DbSession dbSession, SearchMyProjectsRequest request) {
     String userUuid = requireNonNull(userSession.getUuid(), "Current user must be authenticated");
 
-    List<String> componentUuids = dbClient.roleDao().selectEntityUuidsByPermissionAndUserUuid(dbSession, UserRole.ADMIN, userUuid);
-    ComponentQuery dbQuery = ComponentQuery.builder()
-      .setQualifiers(Qualifiers.PROJECT)
-      .setComponentUuids(ImmutableSet.copyOf(componentUuids.subList(0, Math.min(componentUuids.size(), DatabaseUtils.PARTITION_SIZE_FOR_ORACLE))))
-      .build();
+    List<String> entitiesUuid = dbClient.roleDao().selectEntityUuidsByPermissionAndUserUuidAndQualifier(dbSession, UserRole.ADMIN, userUuid, Set.of(Qualifiers.PROJECT));
+
+    ImmutableSet<String> subSetEntityUuids = ImmutableSet.copyOf(entitiesUuid.subList(0, Math.min(entitiesUuid.size(), DatabaseUtils.PARTITION_SIZE_FOR_ORACLE)));
+    Pagination pagination = Pagination.forPage(request.page).andSize(request.pageSize);
+    List<ProjectDto> projectDtos = dbClient.projectDao().selectByUuids(dbSession, subSetEntityUuids, pagination);
+
+    List<BranchDto> branchDtos = dbClient.branchDao().selectMainBranchesByProjectUuids(dbSession, projectDtos.stream().map(ProjectDto::getUuid).collect(Collectors.toSet()));
 
-    return new ProjectsResult(
-      dbClient.componentDao().selectByQuery(dbSession, dbQuery, offset(request.getPage(), request.getPageSize()), request.getPageSize()),
-      dbClient.componentDao().countByQuery(dbSession, dbQuery));
+    return new ProjectsResult(projectDtos, branchDtos, subSetEntityUuids.size());
   }
 
   private static class ProjectsResult {
-    private final List<ComponentDto> projects;
+
+    private final List<ProjectDto> projects;
+    private final List<BranchDto> branches;
     private final int total;
 
-    private ProjectsResult(List<ComponentDto> projects, int total) {
+    private ProjectsResult(List<ProjectDto> projects, List<BranchDto> branches, int total) {
       this.projects = projects;
+      this.branches = branches;
+      assertThatAllCollectionsHaveSameSize(projects, branches);
       this.total = total;
     }
+
+    private static void assertThatAllCollectionsHaveSameSize(List<ProjectDto> projects, List<BranchDto> branches) {
+      if (projects.size() != branches.size()) {
+        throw new IllegalStateException("There must be the same number of projects as the branches.");
+      }
+    }
   }
 
   private static class SearchMyProjectsRequest {
index 59f077e6c0d24e5e765df3c6b3d3be241e5568c9..cc24753be4f47fd9fa7fbd11fbb512db729133cb 100644 (file)
@@ -26,10 +26,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
-import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ProjectLinkDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.LiveMeasureDto;
+import org.sonar.db.project.ProjectDto;
 
 import static com.google.common.collect.ImmutableList.copyOf;
 import static java.util.Objects.requireNonNull;
@@ -37,7 +38,9 @@ import static java.util.function.Function.identity;
 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 
 class SearchMyProjectsData {
-  private final List<ComponentDto> projects;
+
+  private final List<ProjectDto> projects;
+  private final Map<String, String> branchUuidByProjectUuids;
   private final ListMultimap<String, ProjectLinkDto> projectLinksByProjectUuid;
   private final Map<String, SnapshotDto> snapshotsByComponentUuid;
   private final Map<String, String> qualityGateStatuses;
@@ -45,17 +48,20 @@ class SearchMyProjectsData {
 
   private SearchMyProjectsData(Builder builder) {
     this.projects = copyOf(builder.projects);
+    this.branchUuidByProjectUuids = buildBranchUuidByProjectUuidMap(builder.branches);
     this.projectLinksByProjectUuid = buildProjectLinks(builder.projectLinks);
     this.snapshotsByComponentUuid =builder.snapshots.stream().collect(uniqueIndex(SnapshotDto::getComponentUuid, identity()));
     this.qualityGateStatuses = buildQualityGateStatuses(builder.qualityGates);
     this.totalNbOfProject = builder.totalNbOfProjects;
   }
 
+
+
   static Builder builder() {
     return new Builder();
   }
 
-  List<ComponentDto> projects() {
+  List<ProjectDto> projects() {
     return projects;
   }
 
@@ -80,14 +86,29 @@ class SearchMyProjectsData {
     dtos.forEach(projectLink -> projectLinks.put(projectLink.getProjectUuid(), projectLink));
     return projectLinks.build();
   }
+  private static Map<String, String> buildBranchUuidByProjectUuidMap(List<BranchDto> branches) {
+    return branches.stream().collect(Collectors.toMap(BranchDto::getProjectUuid, BranchDto::getUuid));
+  }
 
   private static Map<String, String> buildQualityGateStatuses(List<LiveMeasureDto> measures) {
     return ImmutableMap.copyOf(measures.stream()
       .collect(Collectors.toMap(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getDataAsString)));
   }
 
+  public String mainBranchUuidForProjectUuid(String projectUuid) {
+    String branchUuid = branchUuidByProjectUuids.get(projectUuid);
+    if(branchUuid==null){
+      throw  new IllegalStateException("Project must have a corresponding main branch.");
+    }
+    return branchUuid;
+
+
+  }
+
   static class Builder {
-    private List<ComponentDto> projects;
+
+    private List<ProjectDto> projects;
+    private List<BranchDto> branches;
     private List<ProjectLinkDto> projectLinks;
     private List<SnapshotDto> snapshots;
     private List<LiveMeasureDto> qualityGates;
@@ -97,11 +118,16 @@ class SearchMyProjectsData {
       // enforce method constructor
     }
 
-    Builder setProjects(List<ComponentDto> projects) {
+    Builder setProjects(List<ProjectDto> projects) {
       this.projects = projects;
       return this;
     }
 
+    Builder setBranches(List<BranchDto> branches) {
+      this.branches = branches;
+      return this;
+    }
+
     public Builder setProjectLinks(List<ProjectLinkDto> projectLinks) {
       this.projectLinks = projectLinks;
       return this;
@@ -124,6 +150,7 @@ class SearchMyProjectsData {
 
     SearchMyProjectsData build() {
       requireNonNull(projects);
+      requireNonNull(branches);
       requireNonNull(projectLinks);
       requireNonNull(snapshots);
       requireNonNull(qualityGates);
index 58d0d4b42ba60e7170e59316dd16628a5f63fb49..55c3bf45b1499c689919ca56dafcc9e91955e1d3 100644 (file)
@@ -45,6 +45,7 @@ public class SearchMyProjectsDataTest {
   public void fail_if_projects_links_are_not_provided() {
     Builder builder = underTest
       .setProjects(emptyList())
+      .setBranches(emptyList())
       .setProjectLinks(null)
       .setSnapshots(emptyList())
       .setQualityGates(emptyList())
@@ -57,6 +58,7 @@ public class SearchMyProjectsDataTest {
   public void fail_if_snapshots_are_not_provided() {
     Builder builder = underTest
       .setProjects(emptyList())
+      .setBranches(emptyList())
       .setProjectLinks(emptyList())
       .setSnapshots(null)
       .setQualityGates(emptyList())
@@ -68,7 +70,7 @@ public class SearchMyProjectsDataTest {
   @Test
   public void fail_if_quality_gates_are_not_provided() {
     Builder builder = underTest
-      .setProjects(emptyList())
+      .setBranches(emptyList())
       .setProjectLinks(emptyList())
       .setSnapshots(emptyList())
       .setQualityGates(null);
@@ -79,7 +81,7 @@ public class SearchMyProjectsDataTest {
   @Test
   public void fail_if_total_number_of_projects_is_not_provided() {
     Builder builder = underTest
-      .setProjects(emptyList())
+      .setBranches(emptyList())
       .setProjectLinks(emptyList())
       .setSnapshots(emptyList())
       .setQualityGates(emptyList())