]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7127 Add language parameter to WS api/components/search
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 21 Dec 2015 14:21:13 +0000 (15:21 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 21 Dec 2015 14:21:38 +0000 (15:21 +0100)
20 files changed:
server/sonar-server/src/main/java/org/sonar/server/component/ws/LanguageParamUtils.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/computation/ws/ActivityAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/LanguageParamUtils.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ProjectAssociationActions.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileIdentificationParamUtils.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/SetDefaultAction.java
server/sonar-server/src/main/resources/org/sonar/server/component/ws/search-components-example.json
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchActionTest.java
sonar-db/src/main/java/org/sonar/db/component/ComponentQuery.java
sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml
sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java
sonar-db/src/test/java/org/sonar/db/component/ComponentQueryTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/component/ComponentsWsParameters.java
sonar-ws/src/main/java/org/sonarqube/ws/client/component/SearchWsRequest.java
sonar-ws/src/main/protobuf/ws-components.proto

diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/LanguageParamUtils.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/LanguageParamUtils.java
new file mode 100644 (file)
index 0000000..b82fc64
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.component.ws;
+
+import com.google.common.collect.Collections2;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.core.util.NonNullInputFunction;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class LanguageParamUtils {
+
+  private LanguageParamUtils() {
+    // Utility class
+  }
+
+  public static String getExampleValue(Languages languages) {
+    Language[] languageArray = languages.all();
+    if (languageArray.length > 0) {
+      return languageArray[0].getKey();
+    } else {
+      return "";
+    }
+  }
+
+  public static Collection<String> getLanguageKeys(Languages languages) {
+    return Collections2.transform(Arrays.asList(languages.all()), new NonNullInputFunction<Language, String>() {
+      @Override
+      public String doApply(Language input) {
+        return input.getKey();
+      }
+    });
+  }
+}
index ad46f1d3a50ace6ae35eecd30a6d93b483e4388b..106817ee7604570e476e5202a7192213f7646943 100644 (file)
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.Request;
@@ -48,6 +49,7 @@ import static java.lang.String.format;
 import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
 import static org.sonar.server.ws.WsUtils.checkRequest;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
 import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
 
@@ -58,12 +60,14 @@ public class SearchAction implements ComponentsWsAction {
   private final ResourceTypes resourceTypes;
   private final I18n i18n;
   private final UserSession userSession;
+  private final Languages languages;
 
-  public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession) {
+  public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession, Languages languages) {
     this.dbClient = dbClient;
     this.resourceTypes = resourceTypes;
     this.i18n = i18n;
     this.userSession = userSession;
+    this.languages = languages;
   }
 
   @Override
@@ -81,6 +85,13 @@ public class SearchAction implements ComponentsWsAction {
       .setRequired(true)
       .setExampleValue(format("%s,%s", Qualifiers.PROJECT, Qualifiers.MODULE))
       .setDescription("Comma-separated list of component qualifiers. Possible values are " + buildQualifiersDescription());
+
+    action
+      .createParam(PARAM_LANGUAGE)
+      .setDescription("Language key. If provided, only components for the given language are returned.")
+      .setExampleValue(LanguageParamUtils.getExampleValue(languages))
+      .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+      .setSince("5.4");
   }
 
   @Override
@@ -109,6 +120,7 @@ public class SearchAction implements ComponentsWsAction {
   private static SearchWsRequest toSearchWsRequest(Request request) {
     return new SearchWsRequest()
       .setQualifiers(request.mandatoryParamAsStrings(PARAM_QUALIFIERS))
+      .setLanguage(request.param(PARAM_LANGUAGE))
       .setQuery(request.param(Param.TEXT_QUERY))
       .setPage(request.mandatoryParamAsInt(Param.PAGE))
       .setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));
@@ -147,6 +159,7 @@ public class SearchAction implements ComponentsWsAction {
   private ComponentQuery buildQuery(SearchWsRequest request, List<String> qualifiers) {
     return new ComponentQuery(
       request.getQuery(),
+      request.getLanguage(),
       qualifiers.toArray(new String[qualifiers.size()]));
   }
 
@@ -185,12 +198,16 @@ public class SearchAction implements ComponentsWsAction {
 
     @Override
     public WsComponents.Component apply(@Nonnull ComponentDto dto) {
-      return WsComponents.Component.newBuilder()
+      WsComponents.Component.Builder builder = WsComponents.Component.newBuilder()
         .setId(dto.uuid())
         .setKey(dto.key())
         .setName(dto.name())
-        .setQualifier(dto.qualifier())
-        .build();
+        .setQualifier(dto.qualifier());
+      if (dto.language() != null) {
+        builder.setLanguage(dto.language());
+      }
+
+      return builder.build();
     }
   }
 }
index e7b483eed85eb49b98ce3bdcfb3a11409c120577..962575663074d92cc1c57d4ee9b3e8748927fc05 100644 (file)
@@ -160,7 +160,7 @@ public class ActivityAction implements CeWsAction {
       query.setComponentUuid(componentUuid);
     }
     if (componentQuery != null) {
-      ComponentQuery componentDtoQuery = new ComponentQuery(componentQuery, Qualifiers.PROJECT, Qualifiers.VIEW);
+      ComponentQuery componentDtoQuery = new ComponentQuery(componentQuery, null, Qualifiers.PROJECT, Qualifiers.VIEW);
       List<ComponentDto> componentDtos = dbClient.componentDao().selectByQuery(dbSession, componentDtoQuery, 0, CeActivityQuery.MAX_COMPONENT_UUIDS);
       query.setComponentUuids(Lists.transform(componentDtos, ComponentDtoFunctions.toUuid()));
     }
index 28f096e8d3a99f69061fbe7a99cd19d7df695e54..10aa71531f1169c656a9b0b5acb82519cc1aeb64 100644 (file)
@@ -32,6 +32,7 @@ import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ws.LanguageParamUtils;
 import org.sonarqube.ws.MediaTypes;
 import org.sonar.server.qualityprofile.QProfileExporters;
 import org.sonar.server.qualityprofile.QProfileFactory;
index da8f1393c5588763a02d1470caf823ad08246e9c..cbf98d46ac2999f166b59a96631ccff56ea85339 100644 (file)
@@ -37,6 +37,7 @@ import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ws.LanguageParamUtils;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonarqube.ws.MediaTypes;
 import org.sonar.server.qualityprofile.QProfileBackuper;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/LanguageParamUtils.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/LanguageParamUtils.java
deleted file mode 100644 (file)
index fe7d71f..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.qualityprofile.ws;
-
-import com.google.common.collect.Collections2;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.core.util.NonNullInputFunction;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-class LanguageParamUtils {
-
-  private LanguageParamUtils() {
-    // Utility class
-  }
-
-  static String getExampleValue(Languages languages) {
-    Language[] languageArray = languages.all();
-    if (languageArray.length > 0) {
-      return languageArray[0].getKey();
-    } else {
-      return "";
-    }
-  }
-
-  static Collection<String> getLanguageKeys(Languages languages) {
-    return Collections2.transform(Arrays.asList(languages.all()), new NonNullInputFunction<Language, String>() {
-      @Override
-      public String doApply(Language input) {
-        return input.getKey();
-      }
-    });
-  }
-}
index 037b02cf0bacbcaccfe9482b969b57b13eafda38..49fda68b5395ea9bc9642addade2dbe81eae74a4 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.ws.LanguageParamUtils;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.qualityprofile.QProfile;
 import org.sonar.server.qualityprofile.QProfileLookup;
index 36297c5ece96bde8c622edfc924327a0f70cf349..e135f6b58c7ec073ac0305500d910c86fa4efd21 100644 (file)
@@ -25,6 +25,7 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ws.LanguageParamUtils;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.qualityprofile.QProfileFactory;
 
index 6e55813f8928338b8c30572ac1c6db2c56b8153d..6b63aa04fbcdefdeab37223fdc6b0867c9261ad8 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.server.component.ws.LanguageParamUtils;
 import org.sonar.server.qualityprofile.QProfile;
 import org.sonarqube.ws.QualityProfiles;
 import org.sonarqube.ws.QualityProfiles.SearchWsResponse;
index e00329820451f5874b3c9961fe5b4517fd9797f1..d7b014304c9c02d3d0aefddc2d66688bcc5e2e32 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.component.ws.LanguageParamUtils;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.qualityprofile.QProfile;
 import org.sonar.server.qualityprofile.QProfileFactory;
index 80a9ad94ccae167aff17238aaf4b251d50a7970f..1053ac8d311c16225eebfc90c0dd057aca278c7b 100644 (file)
@@ -15,7 +15,8 @@
       "id": "file-uuid",
       "key": "file-key",
       "qualifier": "FIL",
-      "name": "File Name"
+      "name": "File Name",
+      "language": "java"
     },
     {
       "id": "module-uuid",
index 6020baaa32ece53e079b798094f735f3765b2c0c..d8362cf0a835519a7bcf40e7f803cbaa8c703983 100644 (file)
@@ -24,6 +24,8 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.RailsHandler;
 import org.sonar.api.server.ws.WebService;
@@ -34,7 +36,9 @@ import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class ComponentsWsTest {
   @Rule
@@ -44,10 +48,13 @@ public class ComponentsWsTest {
 
   @Before
   public void setUp() {
+    Languages languages = mock(Languages.class, RETURNS_DEEP_STUBS);
+    when(languages.all()).thenReturn(new Language[0]);
+
     WsTester tester = new WsTester(new ComponentsWs(
       new AppAction(mock(DbClient.class), mock(Durations.class), mock(I18n.class), userSessionRule, mock(ComponentFinder.class)),
       new SearchViewComponentsAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)),
-      new SearchAction(mock(org.sonar.db.DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule)
+      new SearchAction(mock(org.sonar.db.DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule, languages)
       ));
     controller = tester.controller("api/components");
   }
index 5d557311a734a9c6d7e5dcaaf8f1df7460097c5d..c54d3a9c5ceece61cc68d9821f5151015aff19a3 100644 (file)
@@ -23,20 +23,20 @@ package org.sonar.server.component.ws;
 import com.google.common.base.Joiner;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
 import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.ResourceType;
-import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.System2;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDbTester;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ResourceTypesRule;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.UnauthorizedException;
@@ -47,7 +47,6 @@ import org.sonar.server.ws.WsActionTester;
 import org.sonarqube.ws.MediaTypes;
 import org.sonarqube.ws.WsComponents.SearchWsResponse;
 
-import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -56,8 +55,9 @@ import static org.sonar.db.component.ComponentTesting.newFileDto;
 import static org.sonar.db.component.ComponentTesting.newModuleDto;
 import static org.sonar.db.component.ComponentTesting.newProjectDto;
 import static org.sonar.db.component.ComponentTesting.newView;
-import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
 import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
 
 public class SearchActionTest {
   @Rule
@@ -70,15 +70,17 @@ public class SearchActionTest {
   I18nRule i18n = new I18nRule();
 
   WsActionTester ws;
-  ResourceTypes resourceTypes;
+  ResourceTypesRule resourceTypes = new ResourceTypesRule();
+  Languages languages;
 
   @Before
   public void setUp() {
     userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-    resourceTypes = mock(ResourceTypes.class);
-    when(resourceTypes.getAll()).thenReturn(resourceTypes());
+    resourceTypes.setAllQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.DIRECTORY, Qualifiers.FILE);
+    languages = mock(Languages.class);
+    when(languages.all()).thenReturn(javaLanguage());
 
-    ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession));
+    ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession, languages));
 
   }
 
@@ -88,24 +90,21 @@ public class SearchActionTest {
     ComponentDto project = componentDb.insertComponent(
       newProjectDto("project-uuid")
         .setName("Project Name")
-        .setKey("project-key")
-      );
+        .setKey("project-key"));
     ComponentDto module = componentDb.insertComponent(
       newModuleDto("module-uuid", project)
         .setName("Module Name")
-        .setKey("module-key")
-      );
+        .setKey("module-key"));
     componentDb.insertComponent(
       newDirectory(module, "path/to/directoy")
         .setUuid("directory-uuid")
         .setKey("directory-key")
-        .setName("Directory Name")
-      );
+        .setName("Directory Name"));
     componentDb.insertComponent(
       newFileDto(module, "file-uuid")
         .setKey("file-key")
-        .setName("File Name")
-      );
+        .setLanguage("java")
+        .setName("File Name"));
     db.commit();
 
     String response = newRequest(Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.DIRECTORY, Qualifiers.FILE)
@@ -151,6 +150,21 @@ public class SearchActionTest {
     assertThat(response.getComponentsList()).extracting("key").containsExactly("project-_%-key");
   }
 
+  @Test
+  public void search_with_language() throws IOException {
+    componentDb.insertComponent(newProjectDto().setKey("java-project").setLanguage("java"));
+    componentDb.insertComponent(newProjectDto().setKey("cpp-project").setLanguage("cpp"));
+    db.commit();
+
+    InputStream responseStream = newRequest(Qualifiers.PROJECT)
+      .setParam(PARAM_LANGUAGE, "java")
+      .execute().getInputStream();
+    SearchWsResponse response = SearchWsResponse.parseFrom(responseStream);
+
+    assertThat(response.getComponentsCount()).isEqualTo(1);
+    assertThat(response.getComponentsList().get(0).getKey()).isEqualTo("java-project");
+  }
+
   @Test
   public void fail_if_unknown_qualifier_provided() {
     expectedException.expect(BadRequestException.class);
@@ -181,11 +195,22 @@ public class SearchActionTest {
       .setParam(PARAM_QUALIFIERS, Joiner.on(",").join(qualifiers));
   }
 
-  private static List<ResourceType> resourceTypes() {
-    return asList(
-      ResourceType.builder(Qualifiers.PROJECT).build(),
-      ResourceType.builder(Qualifiers.MODULE).build(),
-      ResourceType.builder(Qualifiers.DIRECTORY).build(),
-      ResourceType.builder(Qualifiers.FILE).build());
+  private static Language[] javaLanguage() {
+    return new Language[] {new Language() {
+      @Override
+      public String getKey() {
+        return "java";
+      }
+
+      @Override
+      public String getName() {
+        return "Java";
+      }
+
+      @Override
+      public String[] getFileSuffixes() {
+        return new String[0];
+      }
+    }};
   }
 }
index 57d4536f968a335666df80a43faa728485a8a9df..142d98ce781c4bc45e94d82a3ada4eed7f3b931d 100644 (file)
@@ -30,8 +30,10 @@ import static org.sonar.db.WildcardPosition.AFTER;
 public class ComponentQuery {
   private final String nameOrKeyQuery;
   private final String[] qualifiers;
+  private final String language;
 
-  public ComponentQuery(@Nullable String nameOrKeyQuery, String... qualifiers) {
+  public ComponentQuery(@Nullable String nameOrKeyQuery, String language, String... qualifiers) {
+    this.language = language;
     checkArgument(qualifiers.length > 0, "At least one qualifier must be provided");
 
     this.nameOrKeyQuery = nameOrKeyQuery;
@@ -56,4 +58,9 @@ public class ComponentQuery {
   public String getNameOrKeyQueryToSqlForProjectKey() {
     return buildLikeValue(nameOrKeyQuery, AFTER);
   }
+
+  @CheckForNull
+  public String getLanguage() {
+    return language;
+  }
 }
index f88928f83ca2d3b55bc43af7b24e08a1b3303dbe..0618022f2f8cfea1d86b0727b51a18aea4ec024b 100644 (file)
       <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=",">
         #{qualifier}
       </foreach>
+      <if test="query.language!=null">
+        AND p.language = #{query.language}
+      </if>
       <if test="query.nameOrKeyQuery!=null">
         AND (exists (
         select 1
index 5cf3d42c5f7f283b10bdb6f8da359ab044756811..3c3491ca31e27f0d7fe2218b61052100d305b868 100644 (file)
@@ -683,7 +683,7 @@ public class ComponentDaoTest {
     db.commit();
     componentDb.indexProjects();
 
-    ComponentQuery query = new ComponentQuery("oJect", Qualifiers.PROJECT);
+    ComponentQuery query = new ComponentQuery("oJect", null, Qualifiers.PROJECT);
     List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 1, 3);
 
     assertThat(result).hasSize(3);
@@ -697,7 +697,7 @@ public class ComponentDaoTest {
     db.commit();
     componentDb.indexProjects();
 
-    ComponentQuery query = new ComponentQuery("-\\_%/-", Qualifiers.PROJECT);
+    ComponentQuery query = new ComponentQuery("-\\_%/-", null, Qualifiers.PROJECT);
     List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
 
     assertThat(result).hasSize(1);
@@ -711,13 +711,26 @@ public class ComponentDaoTest {
     db.commit();
     componentDb.indexProjects();
 
-    ComponentQuery query = new ComponentQuery("project-_%-", Qualifiers.PROJECT);
+    ComponentQuery query = new ComponentQuery("project-_%-", null, Qualifiers.PROJECT);
     List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
 
     assertThat(result).hasSize(1);
     assertThat(result.get(0).key()).isEqualTo("project-_%-key");
   }
 
+  @Test
+  public void select_by_query_filter_on_language() {
+    componentDb.insertComponent(newProjectDto().setKey("java-project-key").setLanguage("java"));
+    componentDb.insertComponent(newProjectDto().setKey("cpp-project-key").setLanguage("cpp"));
+    db.commit();
+
+    ComponentQuery query = new ComponentQuery(null, "java", Qualifiers.PROJECT);
+    List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
+
+    assertThat(result).hasSize(1);
+    assertThat(result.get(0).key()).isEqualTo("java-project-key");
+  }
+
   @Test
   public void select_direct_children_of_a_project() {
     ComponentDto project = newProjectDto().setKey("project-key").setUuid("project-uuid");
index 7ba69c6f7b9cf3be3ad0db691ad412c862517896..94dbecd7e22c9336cc68e0ad43447f0f128a886e 100644 (file)
@@ -35,6 +35,6 @@ public class ComponentQueryTest {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("At least one qualifier must be provided");
 
-    underTest = new ComponentQuery(null);
+    underTest = new ComponentQuery(null, "java");
   }
 }
index 9467eb8adc9973ad24bf327e290e8291a7844935..b9739c4480ea4669aea471e8ae187a8f463ceb14 100644 (file)
@@ -30,6 +30,7 @@ public class ComponentsWsParameters {
 
   // parameters
   public static final String PARAM_QUALIFIERS = "qualifiers";
+  public static final String PARAM_LANGUAGE = "language";
   public static final String PARAM_BASE_COMPONENT_ID = "baseComponentId";
   public static final String PARAM_BASE_COMPONENT_KEY = "baseComponentKey";
   public static final String PARAM_STRATEGY = "strategy";
index f537c1d22acc046ac7519c4f51a5591c2e98053a..0d381aedb406d9d4f4781c2356f88ddb1e37efe1 100644 (file)
@@ -31,6 +31,7 @@ public class SearchWsRequest {
   private Integer page;
   private Integer pageSize;
   private String query;
+  private String language;
 
   public List<String> getQualifiers() {
     return qualifiers;
@@ -70,4 +71,14 @@ public class SearchWsRequest {
     this.query = query;
     return this;
   }
+
+  @CheckForNull
+  public String getLanguage() {
+    return language;
+  }
+
+  public SearchWsRequest setLanguage(@Nullable String language) {
+    this.language = language;
+    return this;
+  }
 }
index aad40d8cab27d7e8cccf19f7ff6f33f8264d78dc..03ded8c9bb792863123bfd12759d4ba2b9e99deb 100644 (file)
@@ -47,4 +47,5 @@ message Component {
   optional string description = 5;
   optional string qualifier = 6;
   optional string path = 7;
+  optional string language = 8;
 }