]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6589 move EventRepository out of Component
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 28 May 2015 07:28:53 +0000 (09:28 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 1 Jun 2015 15:08:28 +0000 (17:08 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java
server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java
server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepositoryImpl.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityProfileEventsStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/component/DumbComponent.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityProfileEventsStepTest.java

index c379e1f72eb93e31fba68ff4b3e87d275b2b8215..2bbb79ef1fe185f23d53e48ee23c14809b2bd487 100644 (file)
@@ -21,7 +21,6 @@ package org.sonar.server.computation.component;
 
 import java.util.List;
 import org.sonar.server.computation.context.ComputationContext;
-import org.sonar.server.computation.event.EventRepository;
 import org.sonar.server.computation.step.PopulateComponentsUuidAndKeyStep;
 
 public interface Component {
@@ -62,9 +61,4 @@ public interface Component {
 
   List<Component> getChildren();
 
-  /**
-   * The event repository for the current component
-   */
-  EventRepository getEventRepository();
-
 }
index f0ae5fd951214878183d9a1e17bb1b71fd1449ed..f5952196b02b91c3bdf060e023f7b98d3ef26107 100644 (file)
 package org.sonar.server.computation.component;
 
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import javax.annotation.Nullable;
 import org.sonar.batch.protocol.Constants;
 import org.sonar.batch.protocol.output.BatchReport;
 import org.sonar.server.computation.ComputationContext;
-import org.sonar.server.computation.event.Event;
-import org.sonar.server.computation.event.EventRepository;
 
 import static com.google.common.base.Predicates.notNull;
 import static com.google.common.collect.ImmutableList.copyOf;
 import static com.google.common.collect.Iterables.filter;
-import static java.util.Objects.requireNonNull;
 
 public class ComponentImpl implements Component {
   private final ComputationContext context;
   private final Type type;
   private final BatchReport.Component component;
   private final List<Component> children;
-  private final EventRepository eventRepository = new SetEventRepository();
 
   // Mutable values
   private String key;
@@ -112,23 +106,4 @@ public class ComponentImpl implements Component {
     return context;
   }
 
-  @Override
-  public EventRepository getEventRepository() {
-    return eventRepository;
-  }
-
-  private static class SetEventRepository implements EventRepository {
-    private final Set<Event> events = new HashSet<>();
-
-    @Override
-    public void add(Event event) {
-      events.add(requireNonNull(event));
-    }
-
-    @Override
-    public Iterable<Event> getEvents() {
-      return events;
-    }
-  }
-
 }
index f1040901595ee011eb90f78621c9a90dd372033e..a6a62dc8d2f8fd89ce8b2502378a210ba942cad2 100644 (file)
@@ -37,6 +37,7 @@ import org.sonar.server.computation.activity.ActivityManager;
 import org.sonar.server.computation.batch.BatchReportReaderImpl;
 import org.sonar.server.computation.batch.ReportExtractor;
 import org.sonar.server.computation.component.DbComponentsRefCache;
+import org.sonar.server.computation.event.EventRepositoryImpl;
 import org.sonar.server.computation.component.ProjectSettingsRepository;
 import org.sonar.server.computation.issue.IssueCache;
 import org.sonar.server.computation.issue.IssueComputation;
@@ -115,6 +116,7 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co
       // repositories
       PlatformLanguageRepository.class,
       MeasureRepositoryImpl.class,
+      EventRepositoryImpl.class,
       ProjectSettingsRepository.class,
 
       // component caches
index 1e55c0c18ad5db381ea42b8615d021bfab84c58f..5041e3f82b938a03203217fdea65f8021ed02723 100644 (file)
  */
 package org.sonar.server.computation.event;
 
+import org.sonar.server.computation.component.Component;
+
 public interface EventRepository {
-  void add(Event event);
+  void add(Component component, Event event);
 
-  Iterable<Event> getEvents();
+  Iterable<Event> getEvents(Component component);
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepositoryImpl.java
new file mode 100644 (file)
index 0000000..b65f94e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.event;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import java.util.Collection;
+import java.util.Collections;
+import org.sonar.server.computation.component.Component;
+
+import static java.util.Objects.requireNonNull;
+
+public class EventRepositoryImpl implements EventRepository {
+  private final Multimap<Component, Event> events = HashMultimap.create();
+
+  @Override
+  public void add(Component component, Event event) {
+    events.put(requireNonNull(component), requireNonNull(event));
+  }
+
+  @Override
+  public Iterable<Event> getEvents(Component component) {
+    Collection<Event> res = this.events.get(component);
+    if (res == null) {
+      return Collections.emptySet();
+    }
+    return res;
+  }
+}
index 2e26992c1d23b6ef8bf268f3d625c7c8d80790ed..511bb9b14f612c3d597ad157aff73636b175c253 100644 (file)
@@ -32,6 +32,7 @@ import org.sonar.server.computation.ComputationContext;
 import org.sonar.server.computation.component.Component;
 import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor;
 import org.sonar.server.computation.event.Event;
+import org.sonar.server.computation.event.EventRepository;
 import org.sonar.server.computation.measure.MeasureRepository;
 import org.sonar.server.computation.qualityprofile.QPMeasureData;
 import org.sonar.server.computation.qualityprofile.QualityProfile;
@@ -45,9 +46,11 @@ import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisi
 
 public class QualityProfileEventsStep implements ComputationStep {
   private final MeasureRepository measureRepository;
+  private final EventRepository eventRepository;
 
-  public QualityProfileEventsStep(MeasureRepository measureRepository) {
+  public QualityProfileEventsStep(MeasureRepository measureRepository, EventRepository eventRepository) {
     this.measureRepository = measureRepository;
+    this.eventRepository = eventRepository;
   }
 
   @Override
@@ -105,15 +108,15 @@ public class QualityProfileEventsStep implements ComputationStep {
         "key", profile.getQpKey(),
         "from", UtcDateUtils.formatDateTime(fixDate(from)),
         "to", UtcDateUtils.formatDateTime(fixDate(profile.getRulesUpdatedAt()))));
-    component.getEventRepository().add(createQProfileEvent(component, profile, "Changes in %s", data));
+    eventRepository.add(component, createQProfileEvent(component, profile, "Changes in %s", data));
   }
 
   private void markAsRemoved(Component component, QualityProfile profile) {
-    component.getEventRepository().add(createQProfileEvent(component, profile, "Stop using %s"));
+    eventRepository.add(component, createQProfileEvent(component, profile, "Stop using %s"));
   }
 
   private void markAsAdded(Component component, QualityProfile profile) {
-    component.getEventRepository().add(createQProfileEvent(component, profile, "Use %s"));
+    eventRepository.add(component, createQProfileEvent(component, profile, "Use %s"));
   }
 
   private static Event createQProfileEvent(Component component, QualityProfile profile, String namePattern) {
index 8830ff340df56c423615c1dfd6a55170556b1508..e2f7061f0b42be55011bfba62610f95c67acf6b1 100644 (file)
@@ -26,7 +26,6 @@ import java.util.List;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.sonar.server.computation.context.ComputationContext;
-import org.sonar.server.computation.event.EventRepository;
 
 public class DumbComponent implements Component {
   public static final Component DUMB_PROJECT = new DumbComponent(Type.PROJECT, 1, "PROJECT_KEY", "PROJECT_UUID");
@@ -87,9 +86,4 @@ public class DumbComponent implements Component {
     return context;
   }
 
-  @Override
-  public EventRepository getEventRepository() {
-    throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR);
-  }
-
 }
index 2759dec7c19c14ff03a0f1d5ed87a1d8d2b91e69..0f86e6d7c9d9afed4b2cbeed7b714588831fe8ef 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.computation.step;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
@@ -29,6 +28,9 @@ import java.util.List;
 import java.util.Set;
 import javax.annotation.Nullable;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.resources.AbstractLanguage;
@@ -50,8 +52,14 @@ import org.sonar.server.computation.qualityprofile.QualityProfile;
 import org.sonar.server.db.DbClient;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 import static org.sonar.api.utils.DateUtils.parseDateTime;
 
@@ -65,8 +73,10 @@ public class QualityProfileEventsStepTest {
 
   private MeasureRepository measureRepository = mock(MeasureRepository.class);
   private LanguageRepository languageRepository = mock(LanguageRepository.class);
+  private EventRepository eventRepository = mock(EventRepository.class);
+  private ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
 
-  private QualityProfileEventsStep underTest = new QualityProfileEventsStep(measureRepository);
+  private QualityProfileEventsStep underTest = new QualityProfileEventsStep(measureRepository, eventRepository);
 
   @Test
   public void no_effect_if_no_previous_measure() {
@@ -76,7 +86,7 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    assertThat(context.getRoot().getEventRepository().getEvents()).isEmpty();
+    verifyNoMoreInteractions(eventRepository);
   }
 
   @Test(expected = IllegalStateException.class)
@@ -97,7 +107,7 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    assertThat(context.getRoot().getEventRepository().getEvents()).isEmpty();
+    verifyNoMoreInteractions(eventRepository);
   }
 
   @Test
@@ -110,9 +120,9 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    List<Event> events = Lists.newArrayList(context.getRoot().getEventRepository().getEvents());
-    assertThat(events).hasSize(1);
-    verifyEvent(events.get(0), "Use '" + qp.getQpName() + "' (" + language.getName() + ")", null);
+    verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture());
+    verifyNoMoreInteractions(eventRepository);
+    verifyEvent(eventArgumentCaptor.getValue(), "Use '" + qp.getQpName() + "' (" + language.getName() + ")", null);
   }
 
   @Test
@@ -125,9 +135,9 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    List<Event> events = Lists.newArrayList(context.getRoot().getEventRepository().getEvents());
-    assertThat(events).hasSize(1);
-    verifyEvent(events.get(0), "Use '" + qp.getQpName() + "' (" + qp.getLanguageKey() + ")", null);
+    verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture());
+    verifyNoMoreInteractions(eventRepository);
+    verifyEvent(eventArgumentCaptor.getValue(), "Use '" + qp.getQpName() + "' (" + qp.getLanguageKey() + ")", null);
   }
 
   @Test
@@ -140,9 +150,9 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    List<Event> events = Lists.newArrayList(context.getRoot().getEventRepository().getEvents());
-    assertThat(events).hasSize(1);
-    verifyEvent(events.get(0), "Stop using '" + qp.getQpName() + "' (" + language.getName() + ")", null);
+    verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture());
+    verifyNoMoreInteractions(eventRepository);
+    verifyEvent(eventArgumentCaptor.getValue(), "Stop using '" + qp.getQpName() + "' (" + language.getName() + ")", null);
   }
 
   @Test
@@ -155,9 +165,9 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    List<Event> events = Lists.newArrayList(context.getRoot().getEventRepository().getEvents());
-    assertThat(events).hasSize(1);
-    verifyEvent(events.get(0), "Stop using '" + qp.getQpName() + "' (" + qp.getLanguageKey() + ")", null);
+    verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture());
+    verifyNoMoreInteractions(eventRepository);
+    verifyEvent(eventArgumentCaptor.getValue(), "Stop using '" + qp.getQpName() + "' (" + qp.getLanguageKey() + ")", null);
   }
 
   @Test
@@ -169,7 +179,7 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    assertThat(context.getRoot().getEventRepository().getEvents()).isEmpty();
+    verify(eventRepository, never()).add(any(Component.class), any(Event.class));
   }
 
   @Test
@@ -183,10 +193,9 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    List<Event> events = Lists.newArrayList(context.getRoot().getEventRepository().getEvents());
-    assertThat(events).hasSize(1);
-    verifyEvent(
-      events.get(0),
+    verify(eventRepository).add(eq(context.getRoot()), eventArgumentCaptor.capture());
+    verifyNoMoreInteractions(eventRepository);
+    verifyEvent(eventArgumentCaptor.getValue(),
       "Changes in '" + qp2.getQpName() + "' (" + language.getName() + ")",
       "from=" + UtcDateUtils.formatDateTime(parseDateTime("2011-04-25T01:05:14+0100")) + ";key=" + qp1.getQpKey() + ";to="
         + UtcDateUtils.formatDateTime(parseDateTime("2011-04-25T01:05:18+0100")));
@@ -195,6 +204,14 @@ public class QualityProfileEventsStepTest {
   @Test
   public void verify_detection_with_complex_mix_of_qps() {
     ComputationContext context = newNoChildRootContext();
+    final Set<Event> events = new HashSet<>();
+    doAnswer(new Answer() {
+      @Override
+      public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+        events.add((Event) invocationOnMock.getArguments()[1]);
+        return null;
+      }
+    }).when(eventRepository).add(eq(context.getRoot()), any(Event.class));
 
     mockMeasures(
       context.getRoot(), arrayOf(
@@ -211,7 +228,7 @@ public class QualityProfileEventsStepTest {
 
     underTest.execute(context);
 
-    assertThat(context.getRoot().getEventRepository().getEvents()).extracting("name").containsOnly(
+    assertThat(events).extracting("name").containsOnly(
       "Stop using '" + QP_NAME_2 + "' (" + LANGUAGE_KEY_1 + ")",
       "Use '" + QP_NAME_2 + "' (" + LANGUAGE_KEY_3 + ")",
       "Changes in '" + QP_NAME_1 + "' (" + LANGUAGE_KEY_1 + ")"
@@ -282,7 +299,7 @@ public class QualityProfileEventsStepTest {
     return newContext(new ComponentTreeBuilder() {
       @Override
       public Component build(ComputationContext context) {
-        return new EvenRepoComponent(context, Component.Type.PROJECT, 1);
+        return new DumbComponent(context, Component.Type.PROJECT, 1, "uuid", "key");
       }
     });
   }
@@ -292,30 +309,4 @@ public class QualityProfileEventsStepTest {
       builder, languageRepository);
   }
 
-  private class EvenRepoComponent extends DumbComponent {
-    private final EventRepository eventRepository = new EventRepository() {
-      private final Set<Event> events = new HashSet<>();
-
-      @Override
-      public void add(Event event) {
-        events.add(event);
-      }
-
-      @Override
-      public Iterable<Event> getEvents() {
-        return events;
-      }
-    };
-
-    public EvenRepoComponent(@Nullable org.sonar.server.computation.context.ComputationContext context,
-      Type type, int ref, @Nullable Component... children) {
-      super(context, type, ref, null, null, children);
-    }
-
-    @Override
-    public EventRepository getEventRepository() {
-      return eventRepository;
-    }
-  }
-
 }