From 3475a5114e4282de534d477980acaa6b36714d39 Mon Sep 17 00:00:00 2001 From: Fabrice Bellingard Date: Thu, 22 Mar 2012 14:44:11 +0100 Subject: [PATCH] SONAR-3323 Display tab/page/widget only when required measures exist => new annotation @RequiredMeasure(mandatory={}, oneOf={}) that can be applied on any views. Tested on pages, tabs and widgets --- .../org/sonar/api/web/RequiredMeasures.java | 57 +++++++ .../java/org/sonar/server/ui/JRubyFacade.java | 18 +-- .../java/org/sonar/server/ui/ViewProxy.java | 150 ++++++++++++------ .../main/java/org/sonar/server/ui/Views.java | 32 ++-- .../app/controllers/dashboard_controller.rb | 6 +- .../app/controllers/drilldown_controller.rb | 2 +- .../app/controllers/resource_controller.rb | 2 +- .../webapp/WEB-INF/app/models/snapshot.rb | 10 ++ .../app/views/layouts/_layout.html.erb | 6 +- .../org/sonar/server/ui/ViewProxyTest.java | 82 +++++++++- .../java/org/sonar/server/ui/ViewsTest.java | 51 +++--- 11 files changed, 317 insertions(+), 99 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/web/RequiredMeasures.java diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/web/RequiredMeasures.java b/sonar-plugin-api/src/main/java/org/sonar/api/web/RequiredMeasures.java new file mode 100644 index 00000000000..f89cbddee4f --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/web/RequiredMeasures.java @@ -0,0 +1,57 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.web; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

+ * Annotation used to specify which measures should be available on a snapshot to be able to display a view (page, tab, ...). + * It is possible to give a list of mandatory measures (= if one is not available, the view is not displayed) and/or a list of + * needed measures (only one of them needs to be available). The measures are specified using the metric keys. + *

+ *

+ * Example: the DesignPage absolutely requires the "dsm" measure to be fed in order to be displayed, whatever the language. + * The class will define a @RequiredMeasures(mandatory={"dsm"}) annotation. + *

+ * + * @since 2.15 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface RequiredMeasures { + + /** + * Lists all the measures that must absolutely to be available on the snapshot in order to display the view. + * @return the list of mandatory measures, identified by their metric key + */ + String[] mandatory() default {}; + + /** + * Lists all needed measures required to display the view. If only one of them is available on the snapshot, then the view + * is displayed. + * @return the list of needed measures, identified by their metric key + */ + String[] oneOf() default {}; + +} diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index 76517e30df8..be0d7388ac3 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -153,8 +153,8 @@ public final class JRubyFacade { } - public List> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage) { - return getContainer().getComponentByType(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage); + public List> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) { + return getContainer().getComponentByType(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage, (String[]) availableMeasures); } public List> getWidgets() { @@ -165,20 +165,20 @@ public final class JRubyFacade { return getContainer().getComponentByType(Views.class).getWidget(id); } - public List> getPages(String section, String resourceScope, String resourceQualifier, String resourceLanguage) { - return getContainer().getComponentByType(Views.class).getPages(section, resourceScope, resourceQualifier, resourceLanguage); + public List> getPages(String section, String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) { + return getContainer().getComponentByType(Views.class).getPages(section, resourceScope, resourceQualifier, resourceLanguage, (String[]) availableMeasures); } public List> getResourceTabs() { - return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, null, null, null); + return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, null, null, null, null); } - public List> getResourceTabs(String scope, String qualifier, String language) { - return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, scope, qualifier, language); + public List> getResourceTabs(String scope, String qualifier, String language, Object[] availableMeasures) { + return getContainer().getComponentByType(Views.class).getPages(NavigationSection.RESOURCE_TAB, scope, qualifier, language, (String[]) availableMeasures); } - public List> getResourceTabsForMetric(String scope, String qualifier, String language, String metric) { - return getContainer().getComponentByType(Views.class).getPagesForMetric(NavigationSection.RESOURCE_TAB, scope, qualifier, language, metric); + public List> getResourceTabsForMetric(String scope, String qualifier, String language, Object[] availableMeasures, String metric) { + return getContainer().getComponentByType(Views.class).getPagesForMetric(NavigationSection.RESOURCE_TAB, scope, qualifier, language, (String[]) availableMeasures, metric); } public ViewProxy getPage(String id) { diff --git a/sonar-server/src/main/java/org/sonar/server/ui/ViewProxy.java b/sonar-server/src/main/java/org/sonar/server/ui/ViewProxy.java index e7d09cbcf7d..eb8822713fa 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/ViewProxy.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/ViewProxy.java @@ -31,6 +31,7 @@ import org.sonar.api.web.*; import java.util.Collection; import java.util.Map; +@SuppressWarnings("rawtypes") public class ViewProxy implements Comparable { private V view; @@ -46,35 +47,66 @@ public class ViewProxy implements Comparable { private WidgetLayoutType widgetLayout = WidgetLayoutType.DEFAULT; private boolean isDefaultTab = false; private boolean isWidget = false; + private String[] mandatoryMeasures = {}; + private String[] needOneOfMeasures = {}; public ViewProxy(final V view) { this.view = view; - UserRole userRoleAnnotation = AnnotationUtils.getClassAnnotation(view, UserRole.class); - if (userRoleAnnotation != null) { - userRoles = userRoleAnnotation.value(); + initUserRoles(view); + initSections(view); + initResourceScope(view); + initResourceQualifier(view); + initResourceLanguage(view); + initDefaultTabInfo(view); + initDescription(view); + initWidgetProperties(view); + initWidgetCategory(view); + initWidgetLayout(view); + initRequiredMeasures(view); + + isWidget = (view instanceof Widget); + } + + private void initRequiredMeasures(V view) { + RequiredMeasures requiredMeasuresAnnotation = AnnotationUtils.getClassAnnotation(view, RequiredMeasures.class); + if (requiredMeasuresAnnotation != null) { + mandatoryMeasures = requiredMeasuresAnnotation.mandatory(); + needOneOfMeasures = requiredMeasuresAnnotation.oneOf(); } + } - NavigationSection sectionAnnotation = AnnotationUtils.getClassAnnotation(view, NavigationSection.class); - if (sectionAnnotation != null) { - sections = sectionAnnotation.value(); + private void initWidgetLayout(final V view) { + WidgetLayout layoutAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetLayout.class); + if (layoutAnnotation != null) { + widgetLayout = layoutAnnotation.value(); } + } - ResourceScope scopeAnnotation = AnnotationUtils.getClassAnnotation(view, ResourceScope.class); - if (scopeAnnotation != null) { - resourceScopes = scopeAnnotation.value(); + private void initWidgetCategory(final V view) { + WidgetCategory categAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetCategory.class); + if (categAnnotation != null) { + widgetCategories = categAnnotation.value(); } + } - ResourceQualifier qualifierAnnotation = AnnotationUtils.getClassAnnotation(view, ResourceQualifier.class); - if (qualifierAnnotation != null) { - resourceQualifiers = qualifierAnnotation.value(); + private void initWidgetProperties(final V view) { + WidgetProperties propAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetProperties.class); + if (propAnnotation != null) { + for (WidgetProperty property : propAnnotation.value()) { + widgetPropertiesByKey.put(property.key(), property); + } } + } - ResourceLanguage languageAnnotation = AnnotationUtils.getClassAnnotation(view, ResourceLanguage.class); - if (languageAnnotation != null) { - resourceLanguages = languageAnnotation.value(); + private void initDescription(final V view) { + Description descriptionAnnotation = AnnotationUtils.getClassAnnotation(view, Description.class); + if (descriptionAnnotation != null) { + description = descriptionAnnotation.value(); } + } + private void initDefaultTabInfo(final V view) { DefaultTab defaultTabAnnotation = AnnotationUtils.getClassAnnotation(view, DefaultTab.class); if (defaultTabAnnotation != null) { if (defaultTabAnnotation.metrics().length == 0) { @@ -86,30 +118,41 @@ public class ViewProxy implements Comparable { defaultForMetrics = defaultTabAnnotation.metrics(); } } + } - Description descriptionAnnotation = AnnotationUtils.getClassAnnotation(view, Description.class); - if (descriptionAnnotation != null) { - description = descriptionAnnotation.value(); + private void initResourceLanguage(final V view) { + ResourceLanguage languageAnnotation = AnnotationUtils.getClassAnnotation(view, ResourceLanguage.class); + if (languageAnnotation != null) { + resourceLanguages = languageAnnotation.value(); } + } - WidgetProperties propAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetProperties.class); - if (propAnnotation != null) { - for (WidgetProperty property : propAnnotation.value()) { - widgetPropertiesByKey.put(property.key(), property); - } + private void initResourceQualifier(final V view) { + ResourceQualifier qualifierAnnotation = AnnotationUtils.getClassAnnotation(view, ResourceQualifier.class); + if (qualifierAnnotation != null) { + resourceQualifiers = qualifierAnnotation.value(); } + } - WidgetCategory categAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetCategory.class); - if (categAnnotation != null) { - widgetCategories = categAnnotation.value(); + private void initResourceScope(final V view) { + ResourceScope scopeAnnotation = AnnotationUtils.getClassAnnotation(view, ResourceScope.class); + if (scopeAnnotation != null) { + resourceScopes = scopeAnnotation.value(); } + } - WidgetLayout layoutAnnotation = AnnotationUtils.getClassAnnotation(view, WidgetLayout.class); - if (layoutAnnotation != null) { - widgetLayout = layoutAnnotation.value(); + private void initSections(final V view) { + NavigationSection sectionAnnotation = AnnotationUtils.getClassAnnotation(view, NavigationSection.class); + if (sectionAnnotation != null) { + sections = sectionAnnotation.value(); } + } - isWidget = (view instanceof Widget); + private void initUserRoles(final V view) { + UserRole userRoleAnnotation = AnnotationUtils.getClassAnnotation(view, UserRole.class); + if (userRoleAnnotation != null) { + userRoles = userRoleAnnotation.value(); + } } public V getTarget() { @@ -171,6 +214,24 @@ public class ViewProxy implements Comparable { public boolean supportsMetric(String metricKey) { return ArrayUtils.contains(defaultForMetrics, metricKey); } + + public boolean acceptsAvailableMeasures(String[] availableMeasures) { + for (String mandatoryMeasure : mandatoryMeasures) { + if (!ArrayUtils.contains(availableMeasures, mandatoryMeasure)) { + return false; + } + } + if (needOneOfMeasures.length == 0) { + return true; + } else { + for (String neededMeasure : needOneOfMeasures) { + if (ArrayUtils.contains(availableMeasures, neededMeasure)) { + return true; + } + } + return false; + } + } public boolean isWidget() { return isWidget; @@ -203,7 +264,6 @@ public class ViewProxy implements Comparable { return getId().hashCode(); } - @Override public boolean equals(Object obj) { if (obj == null) { @@ -217,29 +277,29 @@ public class ViewProxy implements Comparable { } ViewProxy rhs = (ViewProxy) obj; return new EqualsBuilder() - .append(getId(), rhs.getId()) - .isEquals(); + .append(getId(), rhs.getId()) + .isEquals(); } @Override public String toString() { return new ToStringBuilder(this) - .append("id", view.getId()) - .append("sections", sections) - .append("userRoles", userRoles) - .append("scopes", resourceScopes) - .append("qualifiers", resourceQualifiers) - .append("languages", resourceLanguages) - .append("metrics", defaultForMetrics) - .toString(); + .append("id", view.getId()) + .append("sections", sections) + .append("userRoles", userRoles) + .append("scopes", resourceScopes) + .append("qualifiers", resourceQualifiers) + .append("languages", resourceLanguages) + .append("metrics", defaultForMetrics) + .toString(); } public int compareTo(ViewProxy other) { return new CompareToBuilder() - .append(getTitle(), other.getTitle()) - .append(getId(), other.getId()) - .toComparison(); + .append(getTitle(), other.getTitle()) + .append(getId(), other.getId()) + .toComparison(); } -} \ No newline at end of file +} diff --git a/sonar-server/src/main/java/org/sonar/server/ui/Views.java b/sonar-server/src/main/java/org/sonar/server/ui/Views.java index 4e95904d529..305daa0a471 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/Views.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/Views.java @@ -19,14 +19,19 @@ */ package org.sonar.server.ui; -import com.google.common.collect.Lists; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + import org.apache.commons.lang.ArrayUtils; import org.sonar.api.ServerComponent; import org.sonar.api.web.Page; import org.sonar.api.web.View; import org.sonar.api.web.Widget; -import java.util.*; +import com.google.common.collect.Lists; public class Views implements ServerComponent { @@ -66,23 +71,23 @@ public class Views implements ServerComponent { } public List> getPages(String section) { - return getPages(section, null, null, null); + return getPages(section, null, null, null, null); } - public List> getPages(String section, String resourceScope, String resourceQualifier, String resourceLanguage) { + public List> getPages(String section, String resourceScope, String resourceQualifier, String resourceLanguage, String[] availableMeasures) { List> result = Lists.newArrayList(); for (ViewProxy proxy : pages) { - if (accept(proxy, section, resourceScope, resourceQualifier, resourceLanguage)) { + if (accept(proxy, section, resourceScope, resourceQualifier, resourceLanguage, availableMeasures)) { result.add(proxy); } } return result; } - public List> getPagesForMetric(String section, String resourceScope, String resourceQualifier, String resourceLanguage, String metric) { + public List> getPagesForMetric(String section, String resourceScope, String resourceQualifier, String resourceLanguage, String[] availableMeasures, String metric) { List> result = Lists.newArrayList(); for (ViewProxy proxy : pages) { - if (accept(proxy, section, resourceScope, resourceQualifier, resourceLanguage) && proxy.supportsMetric(metric)) { + if (accept(proxy, section, resourceScope, resourceQualifier, resourceLanguage, availableMeasures) && proxy.supportsMetric(metric)) { result.add(proxy); } } @@ -93,10 +98,10 @@ public class Views implements ServerComponent { return widgetsPerId.get(id); } - public List> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage) { + public List> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage, String[] availableMeasures) { List> result = Lists.newArrayList(); for (ViewProxy proxy : widgets) { - if (accept(proxy, null, resourceScope, resourceQualifier, resourceLanguage)) { + if (accept(proxy, null, resourceScope, resourceQualifier, resourceLanguage, availableMeasures)) { result.add(proxy); } } @@ -107,11 +112,12 @@ public class Views implements ServerComponent { return Lists.newArrayList(widgets); } - private static boolean accept(ViewProxy proxy, String section, String resourceScope, String resourceQualifier, String resourceLanguage) { + protected static boolean accept(ViewProxy proxy, String section, String resourceScope, String resourceQualifier, String resourceLanguage, String[] availableMeasures) { return acceptNavigationSection(proxy, section) && acceptResourceScope(proxy, resourceScope) && acceptResourceQualifier(proxy, resourceQualifier) - && acceptResourceLanguage(proxy, resourceLanguage); + && acceptResourceLanguage(proxy, resourceLanguage) + && acceptAvailableMeasures(proxy, availableMeasures); } protected static boolean acceptResourceLanguage(ViewProxy proxy, String resourceLanguage) { @@ -129,4 +135,8 @@ public class Views implements ServerComponent { protected static boolean acceptNavigationSection(ViewProxy proxy, String section) { return proxy.isWidget() || section == null || ArrayUtils.contains(proxy.getSections(), section); } + + protected static boolean acceptAvailableMeasures(ViewProxy proxy, String[] availableMeasures) { + return availableMeasures == null || proxy.acceptsAvailableMeasures(availableMeasures); + } } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb index ad1ce1fa10d..674d6509076 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/dashboard_controller.rb @@ -35,9 +35,9 @@ class DashboardController < ApplicationController end else # display the layout of the parent, usually the directory, but display the file viewers - if @resource.last_snapshot + if @snapshot @file = @resource - @project = @resource.last_snapshot.parent.project + @project = @snapshot.parent.project render :action => 'no_dashboard' else redirect_to home_path @@ -186,7 +186,7 @@ class DashboardController < ApplicationController def load_authorized_widget_definitions if @resource - @authorized_widget_definitions = java_facade.getWidgets(@resource.scope, @resource.qualifier, @resource.language) + @authorized_widget_definitions = java_facade.getWidgets(@resource.scope, @resource.qualifier, @resource.language, @snapshot.available_measures) @authorized_widget_definitions=@authorized_widget_definitions.select do |widget| authorized=widget.getUserRoles().size==0 unless authorized diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb index 848e046f371..feb4f8e64eb 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/drilldown_controller.rb @@ -173,7 +173,7 @@ class DrilldownController < ApplicationController def display_metric_viewers?(resource, metric_key) return true if resource.file? - java_facade.getResourceTabsForMetric(resource.scope, resource.qualifier, resource.language, metric_key).each do |tab| + java_facade.getResourceTabsForMetric(resource.scope, resource.qualifier, resource.language, resource.last_snapshot.available_measures, metric_key).each do |tab| tab.getUserRoles().each do |role| if has_role?(role, resource) return true diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb index 9c5b1cfcfc2..bf970cf2a96 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb @@ -113,7 +113,7 @@ class ResourceController < ApplicationController def load_extensions @extensions=[] - java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language).each do |tab| + java_facade.getResourceTabs(@resource.scope, @resource.qualifier, @resource.language, @snapshot.available_measures).each do |tab| if tab.getUserRoles().empty? @extensions< <%= message('dependencies.page') -%> - <% controller.java_facade.getPages(Navigation::SECTION_HOME, nil, nil, nil).each do |page| + <% controller.java_facade.getPages(Navigation::SECTION_HOME, nil, nil, nil, nil).each do |page| selected=request.request_uri.include?("/plugins/home/#{page.getId()}") %>
  • <%= message(page.getId() + '.page', :default => page.getTitle()) -%>
  • @@ -57,7 +57,7 @@ "><%= message('violations_drilldown.page') -%>
  • <%= message('clouds.page') -%>
  • - <% controller.java_facade.getPages(Navigation::SECTION_RESOURCE, @project.scope, @project.qualifier, @project.language).each do |page| %> + <% controller.java_facade.getPages(Navigation::SECTION_RESOURCE, @project.scope, @project.qualifier, @project.language, @project.last_snapshot.available_measures).each do |page| %>
  • "> <%= message(page.getId() + '.page', :default => page.getTitle()) %>
  • @@ -111,7 +111,7 @@ <%= message('default_filters.page') -%>
  • <%= message('default_dashboards.page') -%>
  • - <% controller.java_facade.getPages(Navigation::SECTION_CONFIGURATION, nil, nil, nil).each do |page| %> + <% controller.java_facade.getPages(Navigation::SECTION_CONFIGURATION, nil, nil, nil, nil).each do |page| %>
  • "> <%= message(page.getId() + '.page', :default => page.getTitle()) %>
  • diff --git a/sonar-server/src/test/java/org/sonar/server/ui/ViewProxyTest.java b/sonar-server/src/test/java/org/sonar/server/ui/ViewProxyTest.java index 460832cc7d5..c2ae3c9d7ed 100644 --- a/sonar-server/src/test/java/org/sonar/server/ui/ViewProxyTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ui/ViewProxyTest.java @@ -19,15 +19,23 @@ */ package org.sonar.server.ui; -import org.junit.Test; -import org.sonar.api.web.*; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.number.OrderingComparisons.greaterThan; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertThat; +import org.junit.Test; +import org.sonar.api.web.DefaultTab; +import org.sonar.api.web.NavigationSection; +import org.sonar.api.web.RequiredMeasures; +import org.sonar.api.web.UserRole; +import org.sonar.api.web.View; +import org.sonar.api.web.Widget; +import org.sonar.api.web.WidgetProperties; +import org.sonar.api.web.WidgetProperty; +import org.sonar.api.web.WidgetPropertyType; + public class ViewProxyTest { @Test @@ -52,8 +60,8 @@ public class ViewProxyTest { ViewProxy proxy = new ViewProxy(view); assertThat(proxy.getTarget(), is(view)); - assertArrayEquals(proxy.getSections(), new String[]{NavigationSection.RESOURCE}); - assertArrayEquals(proxy.getUserRoles(), new String[]{UserRole.ADMIN}); + assertArrayEquals(proxy.getSections(), new String[] {NavigationSection.RESOURCE}); + assertArrayEquals(proxy.getUserRoles(), new String[] {UserRole.ADMIN}); } @Test @@ -68,11 +76,10 @@ public class ViewProxyTest { ViewProxy proxy = new ViewProxy(view); assertThat(proxy.getTarget(), is(view)); - assertArrayEquals(proxy.getSections(), new String[]{NavigationSection.HOME}); + assertArrayEquals(proxy.getSections(), new String[] {NavigationSection.HOME}); assertThat(proxy.getUserRoles().length, org.hamcrest.Matchers.is(0)); } - @Test public void isDefaultTab() { @DefaultTab @@ -112,7 +119,7 @@ public class ViewProxyTest { ViewProxy proxy = new ViewProxy(new MyView()); assertThat(proxy.isDefaultTab(), is(false)); - assertThat(proxy.getDefaultTabForMetrics(), is(new String[]{"ncloc", "coverage"})); + assertThat(proxy.getDefaultTabForMetrics(), is(new String[] {"ncloc", "coverage"})); } @Test @@ -133,6 +140,65 @@ public class ViewProxyTest { ViewProxy proxy = new ViewProxy(new WidgetWithOptionalProperties()); assertThat(proxy.hasRequiredProperties(), is(false)); } + + @Test + public void shouldAcceptAvailableMeasuresForNoRequiredMeasures() throws Exception { + class MyView extends FakeView { + MyView() { + super("fake"); + } + } + ViewProxy proxy = new ViewProxy(new MyView()); + + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "ncloc", "coverage"}), is(true)); + } + + @Test + public void shouldAcceptAvailableMeasuresForMandatoryMeasures() throws Exception { + @RequiredMeasures(mandatory = {"lines", "ncloc"}) + class MyView extends FakeView { + MyView() { + super("fake"); + } + } + ViewProxy proxy = new ViewProxy(new MyView()); + + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "ncloc", "coverage"}), is(true)); + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "coverage"}), is(false)); + } + + @Test + public void shouldAcceptAvailableMeasuresForOneOfNeededMeasures() throws Exception { + @RequiredMeasures(oneOf = {"lines", "ncloc"}) + class MyView extends FakeView { + MyView() { + super("fake"); + } + } + ViewProxy proxy = new ViewProxy(new MyView()); + + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "coverage"}), is(true)); + assertThat(proxy.acceptsAvailableMeasures(new String[] {"complexity", "coverage"}), is(false)); + } + + @Test + public void shouldAcceptAvailableMeasuresForMandatoryAndOneOfNeededMeasures() throws Exception { + @RequiredMeasures(mandatory = {"lines", "ncloc"}, oneOf = {"duplications", "duplictated_blocks"}) + class MyView extends FakeView { + MyView() { + super("fake"); + } + } + ViewProxy proxy = new ViewProxy(new MyView()); + + // ok, mandatory measures and 1 needed measure + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "ncloc", "coverage", "duplications"}), is(true)); + // ko, one of the needed measures but not all of the mandatory ones + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "coverage", "duplications"}), is(false)); + // ko, mandatory measures but no one of the needed measures + assertThat(proxy.acceptsAvailableMeasures(new String[] {"lines", "nloc", "coverage", "dsm"}), is(false)); + } + } class FakeView implements View { diff --git a/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java b/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java index fa4bded9aa2..eb83b805941 100644 --- a/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ui/ViewsTest.java @@ -19,6 +19,14 @@ */ package org.sonar.server.ui; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.List; + import org.junit.Test; import org.sonar.api.resources.Java; import org.sonar.api.resources.Qualifiers; @@ -28,14 +36,6 @@ import org.sonar.api.web.Page; import org.sonar.api.web.View; import org.sonar.api.web.Widget; -import java.util.List; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class ViewsTest { private static FakeResourceViewer FAKE_TAB = new FakeResourceViewer(); @@ -75,15 +75,15 @@ public class ViewsTest { @Test public void getWidgets() { final Views views = new Views(VIEWS); - List> widgets = views.getWidgets(null, null, null); + List> widgets = views.getWidgets(null, null, null, null); assertThat(widgets.size(), is(1)); assertThat(widgets.get(0).getTarget(), is(FakeWidget.class)); } @Test public void sortViewsByTitle() { - final Views views = new Views(new View[]{new FakeWidget("ccc", "ccc"), new FakeWidget("aaa", "aaa"), new FakeWidget("bbb", "bbb")}); - List> widgets = views.getWidgets(null, null, null); + final Views views = new Views(new View[] {new FakeWidget("ccc", "ccc"), new FakeWidget("aaa", "aaa"), new FakeWidget("bbb", "bbb")}); + List> widgets = views.getWidgets(null, null, null, null); assertThat(widgets.size(), is(3)); assertThat(widgets.get(0).getId(), is("aaa")); assertThat(widgets.get(1).getId(), is("bbb")); @@ -92,8 +92,8 @@ public class ViewsTest { @Test public void prefixTitleByNumberToDisplayFirst() { - final Views views = new Views(new View[]{new FakeWidget("other", "Other"), new FakeWidget("1id", "1widget"), new FakeWidget("2id", "2widget")}); - List> widgets = views.getWidgets(null, null, null); + final Views views = new Views(new View[] {new FakeWidget("other", "Other"), new FakeWidget("1id", "1widget"), new FakeWidget("2id", "2widget")}); + List> widgets = views.getWidgets(null, null, null, null); assertThat(widgets.size(), is(3)); assertThat(widgets.get(0).getId(), is("1id")); assertThat(widgets.get(1).getId(), is("2id")); @@ -103,7 +103,7 @@ public class ViewsTest { @Test public void acceptNavigationSection() { ViewProxy proxy = mock(ViewProxy.class); - when(proxy.getSections()).thenReturn(new String[]{NavigationSection.RESOURCE}); + when(proxy.getSections()).thenReturn(new String[] {NavigationSection.RESOURCE}); when(proxy.isWidget()).thenReturn(false); assertThat(Views.acceptNavigationSection(proxy, NavigationSection.RESOURCE), is(true)); @@ -112,6 +112,21 @@ public class ViewsTest { assertThat(Views.acceptNavigationSection(proxy, null), is(true)); } + @Test + public void acceptAvailableMeasures() { + ViewProxy proxy = mock(ViewProxy.class); + when(proxy.acceptsAvailableMeasures(new String[] {"lines"})).thenReturn(true); + when(proxy.acceptsAvailableMeasures(new String[] {"ncloc"})).thenReturn(false); + + assertThat(Views.acceptAvailableMeasures(proxy, null), is(true)); + assertThat(Views.acceptAvailableMeasures(proxy, new String[] {"lines"}), is(true)); + assertThat(Views.acceptAvailableMeasures(proxy, new String[] {"ncloc"}), is(false)); + + assertThat(Views.accept(proxy, null, null, null, null, null), is(true)); + assertThat(Views.accept(proxy, null, null, null, null, new String[] {"lines"}), is(true)); + assertThat(Views.accept(proxy, null, null, null, null, new String[] {"ncloc"}), is(false)); + } + @Test public void doNotCheckNavigationSectionOnWidgets() { ViewProxy proxy = mock(ViewProxy.class); @@ -128,7 +143,7 @@ public class ViewsTest { ViewProxy proxy = mock(ViewProxy.class); assertThat(Views.acceptResourceLanguage(proxy, Java.KEY), is(true)); - when(proxy.getResourceLanguages()).thenReturn(new String[]{"foo"}); + when(proxy.getResourceLanguages()).thenReturn(new String[] {"foo"}); assertThat(Views.acceptResourceLanguage(proxy, Java.KEY), is(false)); assertThat(Views.acceptResourceLanguage(proxy, "foo"), is(true)); } @@ -138,7 +153,7 @@ public class ViewsTest { ViewProxy proxy = mock(ViewProxy.class); assertThat(Views.acceptResourceScope(proxy, Scopes.FILE), is(true)); - when(proxy.getResourceScopes()).thenReturn(new String[]{Scopes.PROJECT, Scopes.FILE}); + when(proxy.getResourceScopes()).thenReturn(new String[] {Scopes.PROJECT, Scopes.FILE}); assertThat(Views.acceptResourceScope(proxy, Scopes.FILE), is(true)); assertThat(Views.acceptResourceScope(proxy, Scopes.DIRECTORY), is(false)); } @@ -148,8 +163,8 @@ public class ViewsTest { ViewProxy proxy = mock(ViewProxy.class); assertThat(Views.acceptResourceQualifier(proxy, Scopes.FILE), is(true)); - when(proxy.getResourceQualifiers()).thenReturn(new String[]{Qualifiers.CLASS, Qualifiers.FILE}); + when(proxy.getResourceQualifiers()).thenReturn(new String[] {Qualifiers.CLASS, Qualifiers.FILE}); assertThat(Views.acceptResourceQualifier(proxy, Qualifiers.FILE), is(true)); assertThat(Views.acceptResourceQualifier(proxy, Qualifiers.PACKAGE), is(false)); } -} \ No newline at end of file +} -- 2.39.5