aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2015-05-22 09:34:57 +0200
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2015-05-25 13:27:24 +0200
commit2b93b6e78216b2c7c5f8c1b44bdffdd0714aaaa7 (patch)
tree470ebaf27f9d475860681491a3802d89dbaceb43 /server
parent1528580c9b9e8397b6bdfdefa22f60b37340c097 (diff)
downloadsonarqube-2b93b6e78216b2c7c5f8c1b44bdffdd0714aaaa7.tar.gz
sonarqube-2b93b6e78216b2c7c5f8c1b44bdffdd0714aaaa7.zip
SONAR-6568 add CE specific component "API"
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java91
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java65
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java142
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java35
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java92
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java34
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java304
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java54
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java60
15 files changed, 1030 insertions, 0 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java
new file mode 100644
index 00000000000..70e0d37a607
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitor.java
@@ -0,0 +1,91 @@
+/*
+ * 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.component;
+
+import java.util.Objects;
+
+/**
+ * Implementation of {@link TypeAwareVisitor} that implements a depth first crawling of the
+ * {@link ComponentImpl} tree. It supports a max depth for crawling (component strictly deeper than the specified
+ * type will be ignored).
+ */
+public abstract class ChildFirstTypeAwareVisitor implements TypeAwareVisitor {
+ private final Component.Type maxDepth;
+
+ protected ChildFirstTypeAwareVisitor(Component.Type maxDepth) {
+ this.maxDepth = Objects.requireNonNull(maxDepth);
+ }
+
+ @Override
+ public void visit(Component component) {
+ if (component.getType().isDeeperThan(maxDepth)) {
+ return;
+ }
+
+ if (component.getType() != maxDepth) {
+ for (Component child : component.getChildren()) {
+ visit(child);
+ }
+ }
+
+ switch (component.getType()) {
+ case PROJECT:
+ visitProject(component);
+ break;
+ case MODULE:
+ visitModule(component);
+ break;
+ case DIRECTORY:
+ visitDirectory(component);
+ break;
+ case FILE:
+ visitFile(component);
+ break;
+ default:
+ visitUnknown(component);
+ }
+ }
+
+ @Override
+ public void visitProject(Component tree) {
+ // empty implementation, meant to be override at will by subclasses
+ }
+
+ @Override
+ public void visitModule(Component tree) {
+ // empty implementation, meant to be override at will by subclasses
+ }
+
+ @Override
+ public void visitDirectory(Component tree) {
+ // empty implementation, meant to be override at will by subclasses
+ }
+
+ @Override
+ public void visitFile(Component tree) {
+ // empty implementation, meant to be override at will by subclasses
+ }
+
+ @Override
+ public void visitUnknown(Component tree) {
+ // empty implementation, meant to be override at will by subclasses
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java
new file mode 100644
index 00000000000..b1014dcb54b
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/Component.java
@@ -0,0 +1,65 @@
+/*
+ * 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.component;
+
+import java.util.List;
+import org.sonar.server.computation.context.ComputationContext;
+import org.sonar.server.computation.event.EventRepository;
+import org.sonar.server.computation.measure.MeasureRepository;
+
+public interface Component {
+ enum Type {
+ PROJECT(0), MODULE(1), DIRECTORY(2), FILE(3);
+
+ private final int depth;
+
+ Type(int depth) {
+ this.depth = depth;
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+ public boolean isDeeperThan(Type otherType) {
+ return this.getDepth() > otherType.getDepth();
+ }
+ }
+
+ ComputationContext getContext();
+
+ Type getType();
+
+ // FIXME we should not expose a batch specific information
+ int getRef();
+
+ List<Component> getChildren();
+
+ /**
+ * The event repository for the current component
+ */
+ EventRepository getEventRepository();
+
+ /**
+ * the measure repository for the current component
+ */
+ MeasureRepository getMeasureRepository();
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java
new file mode 100644
index 00000000000..b9a66977021
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentImpl.java
@@ -0,0 +1,142 @@
+/*
+ * 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.component;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.api.measures.Metric;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.computation.ComputationContext;
+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.db.DbClient;
+
+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();
+
+ public ComponentImpl(ComputationContext context, BatchReport.Component component, @Nullable Iterable<Component> children) {
+ this.context = context;
+ this.component = component;
+ this.type = convertType(component.getType());
+ this.children = children == null ? Collections.<Component>emptyList() : copyOf(filter(children, notNull()));
+ }
+
+ private static Type convertType(Constants.ComponentType type) {
+ switch (type) {
+ case PROJECT:
+ return Type.PROJECT;
+ case MODULE:
+ return Type.MODULE;
+ case DIRECTORY:
+ return Type.DIRECTORY;
+ case FILE:
+ return Type.FILE;
+ default:
+ throw new IllegalArgumentException("Unsupported Constants.ComponentType value " + type);
+ }
+ }
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ @Override
+ public int getRef() {
+ return component.getRef();
+ }
+
+ @Override
+ public List<Component> getChildren() {
+ return children;
+ }
+
+ @Override
+ public org.sonar.server.computation.context.ComputationContext getContext() {
+ return context;
+ }
+
+ @Override
+ public EventRepository getEventRepository() {
+ return eventRepository;
+ }
+
+ @Override
+ public MeasureRepository getMeasureRepository() {
+ return new MeasureRepository() {
+ @Override
+ public Optional<MeasureDto> findPrevious(Metric<?> metric) {
+ DbClient dbClient = context.getDbClient();
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ return Optional.fromNullable(
+ dbClient.measureDao().findByComponentKeyAndMetricKey(dbSession, component.getKey(), metric.getKey())
+ );
+ }
+ }
+
+ @Override
+ public Optional<BatchReport.Measure> findCurrent(final Metric<?> metric) {
+ return Optional.fromNullable(Iterables.find(
+ context.getReportReader().readComponentMeasures(component.getRef()),
+ new Predicate<BatchReport.Measure>() {
+ @Override
+ public boolean apply(@Nonnull BatchReport.Measure input) {
+ return input.getMetricKey().equals(metric.getKey());
+ }
+ }
+ ));
+ }
+ };
+ }
+
+ 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;
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java
new file mode 100644
index 00000000000..98e02828f48
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/ComponentVisitor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.component;
+
+public interface ComponentVisitor {
+ void visit(Component tree);
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java
new file mode 100644
index 00000000000..9e59e178935
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/TypeAwareVisitor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.component;
+
+/**
+ * A {@link ComponentVisitor} which can exposes methods which ensure the type of the visited Component.
+ */
+public interface TypeAwareVisitor extends ComponentVisitor {
+ void visitProject(Component tree);
+
+ void visitModule(Component tree);
+
+ void visitDirectory(Component tree);
+
+ void visitFile(Component tree);
+
+ void visitUnknown(Component tree);
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java
new file mode 100644
index 00000000000..4e4e221e7b3
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/component/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.computation.component;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java b/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java
new file mode 100644
index 00000000000..171639acbc4
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/context/ComputationContext.java
@@ -0,0 +1,31 @@
+/*
+ * 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.context;
+
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.language.LanguageRepository;
+
+public interface ComputationContext {
+
+ Component getRoot();
+
+ LanguageRepository getLanguageRepository();
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java
new file mode 100644
index 00000000000..d15e656106a
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/context/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.computation.context;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java
new file mode 100644
index 00000000000..260be3c0474
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/event/Event.java
@@ -0,0 +1,92 @@
+/*
+ * 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 java.util.Objects;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static java.util.Objects.requireNonNull;
+
+
+@Immutable
+public class Event {
+ private final String name;
+ private final Category category;
+ @Nullable
+ private final String data;
+ @Nullable
+ private final String description;
+
+ private Event(String name, Category category, @Nullable String data, @Nullable String description) {
+ this.name = requireNonNull(name);
+ this.category = requireNonNull(category);
+ this.data = data;
+ this.description = description;
+ }
+
+ public static Event createAlert(String name, @Nullable String data, @Nullable String description) {
+ return new Event(name, Category.ALERT, data, description);
+ }
+
+ public static Event createProfile(String name, @Nullable String data, @Nullable String description) {
+ return new Event(name, Category.PROFILE, data, description);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ @Nullable
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Event event = (Event) o;
+ return Objects.equals(name, event.name) &&
+ Objects.equals(category, event.category);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, category);
+ }
+
+ public enum Category {
+ ALERT, PROFILE
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java
new file mode 100644
index 00000000000..1e55c0c18ad
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/event/EventRepository.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+public interface EventRepository {
+ void add(Event event);
+
+ Iterable<Event> getEvents();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java
new file mode 100644
index 00000000000..4a57b598b24
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/event/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.computation.event;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java
new file mode 100644
index 00000000000..38c4e77dfd9
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepository.java
@@ -0,0 +1,34 @@
+/*
+ * 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.measure;
+
+import org.sonar.api.measures.Metric;
+import org.sonar.batch.protocol.output.BatchReport;
+
+import com.google.common.base.Optional;
+import org.sonar.core.measure.db.MeasureDto;
+
+public interface MeasureRepository {
+ // FIXME should not expose MeasureDto from DAO layer
+ Optional<MeasureDto> findPrevious(Metric<?> metric);
+
+ // FIXME should not expose Measure from BatchReport
+ Optional<BatchReport.Measure> findCurrent(Metric<?> metric);
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java
new file mode 100644
index 00000000000..d3b66354cf9
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ChildFirstTypeAwareVisitorTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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.component;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.sonar.server.computation.context.ComputationContext;
+import org.sonar.server.computation.event.EventRepository;
+import org.sonar.server.computation.measure.MeasureRepository;
+
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.spy;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.FILE;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+
+public class ChildFirstTypeAwareVisitorTest {
+
+ private static final String UNSUPPORTED_OPERATION_ERROR = "This node has no repository nor context";
+
+ private static final Component FILE_4 = component(FILE, 4);
+ private static final Component FILE_5 = component(FILE, 5);
+ private static final Component DIRECTORY_3 = component(DIRECTORY, 3, FILE_4, FILE_5);
+ private static final Component MODULE_2 = component(MODULE, 2, DIRECTORY_3);
+ private static final Component COMPONENT_TREE = component(PROJECT, 1, MODULE_2);
+
+ private final ChildFirstTypeAwareVisitor spyProjectVisitor = spy(new ChildFirstTypeAwareVisitor(PROJECT) {});
+ private final ChildFirstTypeAwareVisitor spyModuleVisitor = spy(new ChildFirstTypeAwareVisitor(MODULE) {});
+ private final ChildFirstTypeAwareVisitor spyDirectoryVisitor = spy(new ChildFirstTypeAwareVisitor(DIRECTORY) {});
+ private final ChildFirstTypeAwareVisitor spyFileVisitor = spy(new ChildFirstTypeAwareVisitor(FILE) {});
+ private final InOrder inOrder = inOrder(spyProjectVisitor, spyModuleVisitor, spyDirectoryVisitor, spyFileVisitor);
+
+ @Test(expected = NullPointerException.class)
+ public void non_null_max_depth_fast_fail() {
+ new ChildFirstTypeAwareVisitor(null) {
+ };
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void visit_null_Component_throws_NPE() {
+ spyFileVisitor.visit(null);
+ }
+
+ @Test
+ public void visit_file_with_depth_FILE_calls_visit_file() {
+ Component component = component(FILE, 1);
+ spyFileVisitor.visit(component);
+
+ inOrder.verify(spyFileVisitor).visit(component);
+ inOrder.verify(spyFileVisitor).visitFile(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_module_with_depth_FILE_calls_visit_module() {
+ Component component = component(MODULE, 1);
+ spyFileVisitor.visit(component);
+
+ inOrder.verify(spyFileVisitor).visit(component);
+ inOrder.verify(spyFileVisitor).visitModule(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_directory_with_depth_FILE_calls_visit_directory() {
+ Component component = component(DIRECTORY, 1);
+ spyFileVisitor.visit(component);
+
+ inOrder.verify(spyFileVisitor).visit(component);
+ inOrder.verify(spyFileVisitor).visitDirectory(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_project_with_depth_FILE_calls_visit_project() {
+ Component component = component(PROJECT, 1);
+ spyFileVisitor.visit(component);
+
+ inOrder.verify(spyFileVisitor).visit(component);
+ inOrder.verify(spyFileVisitor).visitProject(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_file_with_depth_DIRECTORY_does_not_call_visit_file() {
+ Component component = component(FILE, 1);
+ spyDirectoryVisitor.visit(component);
+
+ inOrder.verify(spyDirectoryVisitor).visit(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_directory_with_depth_DIRECTORY_calls_visit_directory() {
+ Component component = component(DIRECTORY, 1);
+ spyDirectoryVisitor.visit(component);
+
+ inOrder.verify(spyDirectoryVisitor).visit(component);
+ inOrder.verify(spyDirectoryVisitor).visitDirectory(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_module_with_depth_DIRECTORY_calls_visit_module() {
+ Component component = component(MODULE, 1);
+ spyDirectoryVisitor.visit(component);
+
+ inOrder.verify(spyDirectoryVisitor).visit(component);
+ inOrder.verify(spyDirectoryVisitor).visitModule(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_project_with_depth_DIRECTORY_calls_visit_project() {
+ Component component = component(PROJECT, 1);
+ spyDirectoryVisitor.visit(component);
+
+ inOrder.verify(spyDirectoryVisitor).visit(component);
+ inOrder.verify(spyDirectoryVisitor).visitProject(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_file_with_depth_MODULE_does_not_call_visit_file() {
+ Component component = component(FILE, 1);
+ spyModuleVisitor.visit(component);
+
+ inOrder.verify(spyModuleVisitor).visit(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_directory_with_depth_MODULE_does_not_call_visit_directory() {
+ Component component = component(DIRECTORY, 1);
+ spyModuleVisitor.visit(component);
+
+ inOrder.verify(spyModuleVisitor).visit(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_module_with_depth_MODULE_calls_visit_module() {
+ Component component = component(MODULE, 1);
+ spyModuleVisitor.visit(component);
+
+ inOrder.verify(spyModuleVisitor).visit(component);
+ inOrder.verify(spyModuleVisitor).visitModule(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_project_with_depth_MODULE_calls_visit_project() {
+ Component component = component(MODULE, 1);
+ spyModuleVisitor.visit(component);
+
+ inOrder.verify(spyModuleVisitor).visit(component);
+ inOrder.verify(spyModuleVisitor).visitModule(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_file_with_depth_PROJECT_does_not_call_visit_file() {
+ Component component = component(FILE, 1);
+ spyProjectVisitor.visit(component);
+
+ inOrder.verify(spyProjectVisitor).visit(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_directory_with_depth_PROJECT_does_not_call_visit_directory() {
+ Component component = component(DIRECTORY, 1);
+ spyProjectVisitor.visit(component);
+
+ inOrder.verify(spyProjectVisitor).visit(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_module_with_depth_PROJECT_does_not_call_visit_module() {
+ Component component = component(MODULE, 1);
+ spyProjectVisitor.visit(component);
+
+ inOrder.verify(spyProjectVisitor).visit(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void visit_project_with_depth_PROJECT_calls_visit_project() {
+ Component component = component(PROJECT, 1);
+ spyProjectVisitor.visit(component);
+
+ inOrder.verify(spyProjectVisitor).visit(component);
+ inOrder.verify(spyProjectVisitor).visitProject(component);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void verify_visit_call_when_visit_tree_with_depth_FILE() {
+ spyFileVisitor.visit(COMPONENT_TREE);
+
+ inOrder.verify(spyFileVisitor).visit(COMPONENT_TREE);
+ inOrder.verify(spyFileVisitor).visit(MODULE_2);
+ inOrder.verify(spyFileVisitor).visit(DIRECTORY_3);
+ inOrder.verify(spyFileVisitor).visit(FILE_4);
+ inOrder.verify(spyFileVisitor).visitFile(FILE_4);
+ inOrder.verify(spyFileVisitor).visit(FILE_5);
+ inOrder.verify(spyFileVisitor).visitFile(FILE_5);
+ inOrder.verify(spyFileVisitor).visitDirectory(DIRECTORY_3);
+ inOrder.verify(spyFileVisitor).visitModule(MODULE_2);
+ inOrder.verify(spyFileVisitor).visitProject(COMPONENT_TREE);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void verify_visit_call_when_visit_tree_with_depth_DIRECTORY() {
+ spyDirectoryVisitor.visit(COMPONENT_TREE);
+
+ inOrder.verify(spyDirectoryVisitor).visit(COMPONENT_TREE);
+ inOrder.verify(spyDirectoryVisitor).visit(MODULE_2);
+ inOrder.verify(spyDirectoryVisitor).visit(DIRECTORY_3);
+ inOrder.verify(spyDirectoryVisitor).visitDirectory(DIRECTORY_3);
+ inOrder.verify(spyDirectoryVisitor).visitModule(MODULE_2);
+ inOrder.verify(spyDirectoryVisitor).visitProject(COMPONENT_TREE);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void verify_visit_call_when_visit_tree_with_depth_MODULE() {
+ spyModuleVisitor.visit(COMPONENT_TREE);
+
+ inOrder.verify(spyModuleVisitor).visit(COMPONENT_TREE);
+ inOrder.verify(spyModuleVisitor).visit(MODULE_2);
+ inOrder.verify(spyModuleVisitor).visitModule(MODULE_2);
+ inOrder.verify(spyModuleVisitor).visitProject(COMPONENT_TREE);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void verify_visit_call_when_visit_tree_with_depth_PROJECT() {
+ spyProjectVisitor.visit(COMPONENT_TREE);
+
+ inOrder.verify(spyProjectVisitor).visit(COMPONENT_TREE);
+ inOrder.verify(spyProjectVisitor).visitProject(COMPONENT_TREE);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ private static Component component(final Component.Type type, final int ref, final Component... children) {
+ return new Component() {
+
+ @Override
+ public Type getType() {
+ return type;
+ }
+
+ @Override
+ public int getRef() {
+ return ref;
+ }
+
+ @Override
+ public List<Component> getChildren() {
+ return children == null ? Collections.<Component>emptyList() : ImmutableList.copyOf(Arrays.asList(children));
+ }
+
+ @Override
+ public ComputationContext getContext() {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR);
+ }
+
+ @Override
+ public EventRepository getEventRepository() {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR);
+ }
+
+ @Override
+ public MeasureRepository getMeasureRepository() {
+ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR);
+ }
+ };
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java
new file mode 100644
index 00000000000..c6b0d901f0e
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/component/ComponentTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.component;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+
+public class ComponentTest {
+ @Test
+ public void verify_type_is_deeper_than_when_comparing_to_itself() throws Exception {
+ for (Component.Type type : Component.Type.values()) {
+ assertThat(type.isDeeperThan(type)).isFalse();
+ }
+ }
+
+ @Test
+ public void FILE_type_is_deeper_than_all_other_types() throws Exception {
+ assertThat(Component.Type.FILE.isDeeperThan(DIRECTORY)).isTrue();
+ assertThat(Component.Type.FILE.isDeeperThan(MODULE)).isTrue();
+ assertThat(Component.Type.FILE.isDeeperThan(PROJECT)).isTrue();
+ }
+
+ @Test
+ public void DIRECTORY_type_is_deeper_than_MODULE_and_PROJECT() throws Exception {
+ assertThat(Component.Type.DIRECTORY.isDeeperThan(MODULE)).isTrue();
+ assertThat(Component.Type.DIRECTORY.isDeeperThan(PROJECT)).isTrue();
+ }
+
+ @Test
+ public void MODULE_type_is_deeper_than_PROJECT() throws Exception {
+ assertThat(Component.Type.MODULE.isDeeperThan(PROJECT)).isTrue();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java
new file mode 100644
index 00000000000..4726dd2dfed
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/event/EventTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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 org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EventTest {
+
+ private static final String SOME_NAME = "someName";
+ private static final String SOME_DATA = "some data";
+ private static final String SOME_DESCRIPTION = "some description";
+
+ @Test(expected = NullPointerException.class)
+ public void createAlert_fail_fast_null_check_on_null_name() {
+ Event.createAlert(null, SOME_DATA, SOME_DESCRIPTION);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void createProfile_fail_fast_null_check_on_null_name() {
+ Event.createProfile(null, SOME_DATA, SOME_DESCRIPTION);
+ }
+
+ @Test
+ public void createAlert_verify_fields() {
+ Event event = Event.createAlert(SOME_NAME, SOME_DATA, SOME_DESCRIPTION);
+ assertThat(event.getName()).isEqualTo(SOME_NAME);
+ assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
+ assertThat(event.getData()).isEqualTo(SOME_DATA);
+ assertThat(event.getDescription()).isEqualTo(SOME_DESCRIPTION);
+ }
+
+ @Test
+ public void createProfile_verify_fields() {
+ Event event = Event.createProfile(SOME_NAME, SOME_DATA, SOME_DESCRIPTION);
+ assertThat(event.getName()).isEqualTo(SOME_NAME);
+ assertThat(event.getCategory()).isEqualTo(Event.Category.PROFILE);
+ assertThat(event.getData()).isEqualTo(SOME_DATA);
+ assertThat(event.getDescription()).isEqualTo(SOME_DESCRIPTION);
+ }
+
+}