]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8847 Persist copy_component_uuid for local views
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 23 Feb 2017 16:28:33 +0000 (17:28 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 28 Feb 2017 13:35:18 +0000 (14:35 +0100)
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/Component.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/SubViewAttributes.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistComponentsStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ComponentImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ReportComponent.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/component/ViewsComponent.java
server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/step/ViewsPersistComponentsStepTest.java

index 8426608c3c47a039f147706c7aedc214a0161704..b89efeaad9947da3fbb92d354d6dd6b41a5d3070 100644 (file)
@@ -105,4 +105,11 @@ public interface Component {
    * @throws IllegalStateException if the Component's type is not {@link Type#PROJECT_VIEW}
    */
   ProjectViewAttributes getProjectViewAttributes();
+
+  /**
+   * The attributes of the Component if it's type is {@link Type#SUBVIEW}.
+   *
+   * @throws IllegalStateException if the Component's type is not {@link Type#SUBVIEW}
+   */
+  SubViewAttributes getSubViewAttributes();
 }
index 1961da1920edb725c13e6f5859cdf3f6bdf2fde0..1a9c96008ef822650f8f6ad2dacc7275d4f005f1 100644 (file)
@@ -102,7 +102,12 @@ public class ComponentImpl implements Component {
 
   @Override
   public ProjectViewAttributes getProjectViewAttributes() {
-    throw new IllegalStateException("Only component of type PROJECT_VIEW have a FileAttributes object");
+    throw new IllegalStateException("Only component of type PROJECT_VIEW have a ProjectViewAttributes object");
+  }
+
+  @Override
+  public SubViewAttributes getSubViewAttributes() {
+    throw new IllegalStateException("Only component of type SUBVIEW have a SubViewAttributes object");
   }
 
   public static Builder builder(Type type) {
@@ -125,7 +130,7 @@ public class ComponentImpl implements Component {
     private FileAttributes fileAttributes;
     private final List<Component> children = new ArrayList<>();
 
-    private Builder(Type type){
+    private Builder(Type type) {
       this.type = requireNonNull(type, "type can't be null");
     }
 
@@ -159,7 +164,7 @@ public class ComponentImpl implements Component {
       return this;
     }
 
-    public Builder setFileAttributes(@Nullable  FileAttributes fileAttributes) {
+    public Builder setFileAttributes(@Nullable FileAttributes fileAttributes) {
       this.fileAttributes = fileAttributes;
       return this;
     }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/SubViewAttributes.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/SubViewAttributes.java
new file mode 100644 (file)
index 0000000..e773988
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.computation.task.projectanalysis.component;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+public class SubViewAttributes {
+  private final String originalViewUuid;
+
+  public SubViewAttributes(@Nullable String originalViewUuid) {
+    this.originalViewUuid = originalViewUuid;
+  }
+
+  /**
+   * Return the original view uuid when the sub view is a local view
+   */
+  @CheckForNull
+  public String getOriginalViewUuid() {
+    return originalViewUuid;
+  }
+
+  @Override
+  public String toString() {
+    return "SubViewAttributes{" +
+      "originalViewUuid='" + originalViewUuid + '\'' +
+      '}';
+  }
+}
index f20245b652fc54f05cf18425dc3d2237a82ac48c..6d793c70f9e63eaf2c377f973f2a6941c710ba02 100644 (file)
@@ -320,6 +320,7 @@ public class PersistComponentsStep implements ComputationStep {
     res.setName(subView.getName());
     res.setDescription(subView.getDescription());
     res.setLongName(res.name());
+    res.setCopyComponentUuid(subView.getSubViewAttributes().getOriginalViewUuid());
 
     setRootAndParentModule(res, path);
 
index e9843431e31e3d663d0e38415abaffbe64bcb9dc..0f4f0b2d6861faae177f19907ea1a84de3b42b33 100644 (file)
@@ -103,6 +103,21 @@ public class ComponentImplTest {
       });
   }
 
+  @Test
+  public void getSubViewAttributes_throws_ISE_if_component_is_not_have_type_SUBVIEW() {
+    Arrays.stream(Component.Type.values())
+      .filter(type -> type != FILE)
+      .forEach((componentType) -> {
+        ComponentImpl component = buildSimpleComponent(componentType, componentType.name()).build();
+        try {
+          component.getSubViewAttributes();
+          fail("A IllegalStateException should have been raised");
+        } catch (IllegalStateException e) {
+          assertThat(e).hasMessage("Only component of type SUBVIEW have a SubViewAttributes object");
+        }
+      });
+  }
+
   @Test
   public void isUnitTest_returns_true_if_IsTest_is_set_in_BatchComponent() {
     ComponentImpl component = buildSimpleComponent(FILE, "file").setFileAttributes(new FileAttributes(true, null, 1)).build();
index c90898d22424b4f5da1a757d9c9ae72c69b74024..3d11af6d2a428a10b787d25f001eea79854fe04b 100644 (file)
@@ -116,6 +116,11 @@ public class ReportComponent implements Component {
     throw new IllegalStateException("Only component of type PROJECT_VIEW can have a ProjectViewAttributes object");
   }
 
+  @Override
+  public SubViewAttributes getSubViewAttributes() {
+    throw new IllegalStateException("Only component of type SUBVIEW have a SubViewAttributes object");
+  }
+
   @Override
   public boolean equals(@Nullable Object o) {
     if (this == o) {
index 384b57a9a147d92792a96d11a0e42d18214f2053..06a331e68fa9afe1cc15ff5f05549adec25efd5f 100644 (file)
@@ -46,10 +46,12 @@ public class ViewsComponent implements Component {
   private final List<Component> children;
   @CheckForNull
   private final ProjectViewAttributes projectViewAttributes;
+  @CheckForNull
+  private final SubViewAttributes subViewAttributes;
 
   private ViewsComponent(Type type, String key, @Nullable String uuid, @Nullable String name, @Nullable String description,
     List<Component> children,
-    @Nullable ProjectViewAttributes projectViewAttributes) {
+    @Nullable ProjectViewAttributes projectViewAttributes, @Nullable SubViewAttributes subViewAttributes) {
     checkArgument(type.isViewsType(), "Component type must be a Views type");
     this.type = type;
     this.key = requireNonNull(key);
@@ -58,6 +60,7 @@ public class ViewsComponent implements Component {
     this.description = description;
     this.children = ImmutableList.copyOf(children);
     this.projectViewAttributes = projectViewAttributes;
+    this.subViewAttributes = subViewAttributes;
   }
 
   public static Builder builder(Type type, String key) {
@@ -80,6 +83,8 @@ public class ViewsComponent implements Component {
     private List<Component> children = new ArrayList<>();
     @CheckForNull
     private ProjectViewAttributes projectViewAttributes;
+    @CheckForNull
+    private SubViewAttributes subViewAttributes;
 
     private Builder(Type type, String key) {
       this.type = type;
@@ -111,6 +116,11 @@ public class ViewsComponent implements Component {
       return this;
     }
 
+    public Builder setSubViewAttributes(@Nullable SubViewAttributes subViewAttributes) {
+      this.subViewAttributes = subViewAttributes;
+      return this;
+    }
+
     public Builder addChildren(Component... c) {
       for (Component viewsComponent : c) {
         checkArgument(viewsComponent.getType().isViewsType());
@@ -120,7 +130,7 @@ public class ViewsComponent implements Component {
     }
 
     public ViewsComponent build() {
-      return new ViewsComponent(type, key, uuid, name, description, children, projectViewAttributes);
+      return new ViewsComponent(type, key, uuid, name, description, children, projectViewAttributes, subViewAttributes);
     }
   }
 
@@ -172,6 +182,12 @@ public class ViewsComponent implements Component {
     return this.projectViewAttributes;
   }
 
+  @Override
+  public SubViewAttributes getSubViewAttributes() {
+    checkState(this.type != Type.SUBVIEW || this.subViewAttributes != null, "A SubViewAttributes object should have been set");
+    return this.subViewAttributes;
+  }
+
   @Override
   public String toString() {
     return "ViewsComponent{" +
@@ -181,6 +197,7 @@ public class ViewsComponent implements Component {
       ", name='" + name + '\'' +
       ", children=" + children +
       ", projectViewAttributes=" + projectViewAttributes +
+      ", subViewAttributes=" + subViewAttributes +
       '}';
   }
 
index 8cbeeda2489b51c4fc3a8455e831b15d3a010545..ebb89f81bf210eff6aab4cc5c0c0d8a8e77e61f6 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.computation.task.projectanalysis.step;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import javax.annotation.Nullable;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -37,6 +38,7 @@ import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetada
 import org.sonar.server.computation.task.projectanalysis.component.MutableDbIdsRepositoryRule;
 import org.sonar.server.computation.task.projectanalysis.component.MutableDisabledComponentsHolder;
 import org.sonar.server.computation.task.projectanalysis.component.ProjectViewAttributes;
+import org.sonar.server.computation.task.projectanalysis.component.SubViewAttributes;
 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
 import org.sonar.server.computation.task.projectanalysis.component.ViewsComponent;
 import org.sonar.server.computation.task.step.ComputationStep;
@@ -151,7 +153,7 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
     treeRootHolder.setRoot(
       createViewBuilder()
         .addChildren(
-          createSubView1Builder().build())
+          createSubView1Builder(null).build())
         .build());
 
     underTest.execute();
@@ -165,6 +167,22 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
     assertDtoIsSubView1(viewDto, sv1Dto);
   }
 
+  @Test
+  public void persist_empty_subview_having_original_view_uuid() {
+    treeRootHolder.setRoot(
+      createViewBuilder()
+        .addChildren(
+          createSubView1Builder("ORIGINAL_UUID").build())
+        .build());
+
+    underTest.execute();
+
+    assertRowsCountInTableProjects(2);
+
+    ComponentDto subView = getComponentFromDb(SUBVIEW_1_KEY);
+    assertThat(subView.getCopyResourceUuid()).isEqualTo("ORIGINAL_UUID");
+  }
+
   @Test
   public void persist_existing_empty_subview_under_existing_view() {
     ComponentDto viewDto = newViewDto(dbTester.organizations().insert());
@@ -174,7 +192,7 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
     treeRootHolder.setRoot(
       createViewBuilder()
         .addChildren(
-          createSubView1Builder().build())
+          createSubView1Builder(null).build())
         .build());
 
     underTest.execute();
@@ -192,7 +210,7 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
     treeRootHolder.setRoot(
       createViewBuilder()
         .addChildren(
-          createSubView1Builder().build())
+          createSubView1Builder(null).build())
         .build());
 
     underTest.execute();
@@ -211,7 +229,7 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
     treeRootHolder.setRoot(
       createViewBuilder()
         .addChildren(
-          createSubView1Builder()
+          createSubView1Builder(null)
             .addChildren(
               createProjectView1Builder(project, null).build())
             .build())
@@ -307,12 +325,42 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
     assertDtoIsProjectView1(pv1Dto, view, view, project2);
   }
 
+  @Test
+  public void update_copy_component_uuid_of_sub_view() {
+    OrganizationDto organizationDto = dbTester.organizations().insert();
+    ComponentDto view = newViewDto(organizationDto);
+    ComponentDto subView = newSubViewDto(view).setCopyComponentUuid("OLD_COPY");
+    persistComponents(view, subView);
+
+    treeRootHolder.setRoot(
+      createViewBuilder()
+        .addChildren(
+          createSubView1Builder("NEW_COPY").build())
+        .build());
+
+    underTest.execute();
+
+    // commit functional transaction -> copies B-fields to A-fields
+    dbClient.componentDao().applyBChangesForRootComponentUuid(dbTester.getSession(), view.uuid());
+    dbTester.commit();
+
+    ComponentDto subViewReloaded = getComponentFromDb(SUBVIEW_1_KEY);
+    assertThat(subViewReloaded.getCopyResourceUuid()).isEqualTo("NEW_COPY");
+  }
+
   private static ViewsComponent.Builder createViewBuilder() {
-    return builder(VIEW, VIEW_KEY).setUuid(VIEW_UUID).setName(VIEW_NAME).setDescription(VIEW_DESCRIPTION);
+    return builder(VIEW, VIEW_KEY)
+      .setUuid(VIEW_UUID)
+      .setName(VIEW_NAME)
+      .setDescription(VIEW_DESCRIPTION);
   }
 
-  private ViewsComponent.Builder createSubView1Builder() {
-    return builder(SUBVIEW, SUBVIEW_1_KEY).setUuid(SUBVIEW_1_UUID).setName(SUBVIEW_1_NAME).setDescription(SUBVIEW_1_DESCRIPTION);
+  private ViewsComponent.Builder createSubView1Builder(@Nullable String originalViewUuid) {
+    return builder(SUBVIEW, SUBVIEW_1_KEY)
+      .setUuid(SUBVIEW_1_UUID)
+      .setName(SUBVIEW_1_NAME)
+      .setDescription(SUBVIEW_1_DESCRIPTION)
+      .setSubViewAttributes(new SubViewAttributes(originalViewUuid));
   }
 
   private static ViewsComponent.Builder createProjectView1Builder(ComponentDto project, Long analysisDate) {
@@ -346,6 +394,11 @@ public class ViewsPersistComponentsStepTest extends BaseStepTest {
       .setName(VIEW_NAME);
   }
 
+  private ComponentDto newSubViewDto(ComponentDto rootView) {
+    return ComponentTesting.newSubView(rootView, SUBVIEW_1_UUID, SUBVIEW_1_KEY)
+      .setName(SUBVIEW_1_NAME);
+  }
+
   /**
    * Assertions to verify the DTO created from {@link #createViewBuilder()}
    */