]> source.dussan.org Git - sonarqube.git/commitdiff
rename Collectors to MoreCollectors 1891/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 3 Apr 2017 13:13:02 +0000 (15:13 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 3 Apr 2017 13:13:02 +0000 (15:13 +0200)
123 files changed:
server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java
server/sonar-db-core/src/test/java/org/sonar/db/DatabaseUtilsTest.java
server/sonar-db-dao/src/main/java/org/sonar/db/KeyLongValue.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueChangeDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationQuery.java
server/sonar-db-dao/src/main/java/org/sonar/db/permission/UserPermissionDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java
server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/notification/NotificationDbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDbTester.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/history/MigrationHistoryImpl.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/CreateTableBuilder.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/sql/DropColumnsBuilder.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/step/MigrationStepRegistryImpl.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v62/DropIssueFiltersTables.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v62/DropMeasureFiltersTables.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v62/DropRelatedDashboardTables.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v62/UpdateQualityGateConditionsOnCoverage.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v56/PopulateInitialSchemaTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v64/PopulateOrganizationMembersTableTest.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v64/SetCopyComponentUuidOnLocalViewsTest.java
server/sonar-server/src/main/java/org/sonar/server/authentication/UserIdentityAuthenticator.java
server/sonar-server/src/main/java/org/sonar/server/authentication/event/AuthenticationEventImpl.java
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskAction.java
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java
server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java
server/sonar-server/src/main/java/org/sonar/server/component/index/ComponentIndex.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/FilterParser.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidator.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/SuggestionsAction.java
server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
server/sonar-server/src/main/java/org/sonar/server/computation/queue/PurgeCeActivities.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/component/ComponentRootBuilder.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/qualitygate/QualityGateServiceImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/scm/DbScmInfo.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/ComputeMeasureVariationsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/PersistComponentsStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/step/QualityGateMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookPostTask.java
server/sonar-server/src/main/java/org/sonar/server/es/EsUtils.java
server/sonar-server/src/main/java/org/sonar/server/es/IndexType.java
server/sonar-server/src/main/java/org/sonar/server/favorite/FavoriteFinder.java
server/sonar-server/src/main/java/org/sonar/server/favorite/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/IssueFieldsSetter.java
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryFactory.java
server/sonar-server/src/main/java/org/sonar/server/issue/TransitionAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/TransitionService.java
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/BulkChangeAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/ChangelogAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/DeleteCommentAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/EditCommentAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java
server/sonar-server/src/main/java/org/sonar/server/license/ws/ListAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresDoc.java
server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeDataLoader.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchHistoryResponseFactory.java
server/sonar-server/src/main/java/org/sonar/server/measure/ws/SearchHistoryResult.java
server/sonar-server/src/main/java/org/sonar/server/notification/NotificationUpdater.java
server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java
server/sonar-server/src/main/java/org/sonar/server/notification/ws/ListAction.java
server/sonar-server/src/main/java/org/sonar/server/organization/ws/DeleteAction.java
server/sonar-server/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateService.java
server/sonar-server/src/main/java/org/sonar/server/permission/index/PermissionIndexer.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java
server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java
server/sonar-server/src/main/java/org/sonar/server/platform/web/RedirectFilter.java
server/sonar-server/src/main/java/org/sonar/server/platform/ws/LogsAction.java
server/sonar-server/src/main/java/org/sonar/server/project/ws/IndexAction.java
server/sonar-server/src/main/java/org/sonar/server/projectanalysis/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/projectanalysis/ws/SearchResponseBuilder.java
server/sonar-server/src/main/java/org/sonar/server/projectanalysis/ws/SearchResults.java
server/sonar-server/src/main/java/org/sonar/server/projecttag/ws/SetAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QgateProjectFinder.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ValidRatingMetrics.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/CachingRuleActivatorContextFactory.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/DefinedQProfileRepositoryImpl.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QPMeasureData.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/index/ActiveRuleIndexer.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ChangelogLoader.java
server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/DeleteAction.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/QProfileReference.java
server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/ActiveRuleCompleter.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java
server/sonar-server/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/serverid/ws/ShowAction.java
server/sonar-server/src/main/java/org/sonar/server/setting/ws/ResetAction.java
server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
server/sonar-server/src/main/java/org/sonar/server/ui/PageRepository.java
server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/UserUpdater.java
server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/ws/WebServiceFilter.java
server/sonar-server/src/main/java/org/sonar/server/ws/ws/ListAction.java
server/sonar-server/src/test/java/org/sonar/server/authentication/SsoAuthenticatorTest.java
server/sonar-server/src/test/java/org/sonar/server/authentication/UserIdentityAuthenticatorTest.java
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/index/FooIndex.java
server/sonar-server/src/test/java/org/sonar/server/permission/index/PermissionIndexerDaoTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/DefinedQProfileCreationImplTest.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/DefinedQProfileRepositoryRule.java
server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ChangeParentActionTest.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWsMediumTest.java
sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java
sonar-core/src/main/java/org/sonar/core/util/stream/Collectors.java [deleted file]
sonar-core/src/main/java/org/sonar/core/util/stream/MoreCollectors.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/util/stream/CollectorsTest.java [deleted file]
sonar-core/src/test/java/org/sonar/core/util/stream/MoreCollectorsTest.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/source/ZeroCoverageSensor.java

index 3295140ed3d9a737513da1e38509245a7bb968e4..c5a7a4c6b3190f99b91040bbdda53871b49259ce 100644 (file)
@@ -63,7 +63,7 @@ import org.dbunit.ext.mssql.InsertIdentityOperation;
 import org.dbunit.operation.DatabaseOperation;
 import org.junit.rules.ExternalResource;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.Lists.asList;
@@ -478,7 +478,7 @@ public class AbstractDbTester<T extends CoreTestDb> extends ExternalResource {
         columnNames.stream()
           .sorted(PkColumn.ORDERING_BY_INDEX)
           .map(PkColumn::getName)
-          .collect(Collectors.toList()));
+          .collect(MoreCollectors.toList()));
     }
   }
 
index d5855c87a2c695bafd2a27f8745f391ee6adbb1f..c820f7996bc58822985df9fbd4c79de3e323d52f 100644 (file)
@@ -36,7 +36,7 @@ import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.dialect.Oracle;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -261,7 +261,7 @@ public class DatabaseUtilsTest {
     List<String> outputs = DatabaseUtils.executeLargeInputs(inputs, input -> {
       // Check that each partition is only done on 1000 elements max
       assertThat(input.size()).isLessThanOrEqualTo(1000);
-      return input.stream().map(String::valueOf).collect(Collectors.toList());
+      return input.stream().map(String::valueOf).collect(MoreCollectors.toList());
     });
 
     assertThat(outputs).isEqualTo(expectedOutputs);
index 7ade1b65ddeb8fd6e9db11611523acbf0c14acb8..29aac76218e9800ee024ee4a1a6e297cce81330d 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.db;
 import java.util.List;
 import java.util.Map;
 
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 
 public class KeyLongValue {
 
index dc294c166eefd11768253a2cbd75a1284c234f55..9a9fa026968caa50fd5c525b6f926634d723c152 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 import org.sonar.core.issue.FieldDiffs;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 
@@ -36,7 +36,7 @@ public class IssueChangeDao implements Dao {
     return selectByTypeAndIssueKeys(session, singletonList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)
       .stream()
       .map(IssueChangeDto::toFieldDiffs)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   public List<IssueChangeDto> selectChangelogOfNonClosedIssuesByComponent(DbSession session, String componentUuid) {
index 794c7ca8fcba15c4e811077e8dcbccd395097976..cfa220de49323d062ecba1d405ec37488432fbd4 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
-import static org.sonar.core.util.stream.Collectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 
 public class OrganizationQuery {
   private static final OrganizationQuery NO_QUERY = newOrganizationQueryBuilder().build();
index 0c3710abcbdac77e9fc3a8f6301039afbc2c8dc9..357d6f56d863c42ed49603df414aac3969513fdd 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Collection;
 import java.util.List;
 import javax.annotation.Nullable;
 import org.apache.ibatis.session.RowBounds;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.Dao;
 import org.sonar.db.DatabaseUtils;
 import org.sonar.db.DbSession;
@@ -62,7 +62,7 @@ public class UserPermissionDao implements Dao {
     return dtos.stream()
       .map(UserPermissionDto::getUserId)
       .distinct()
-      .collect(Collectors.toList(dtos.size()));
+      .collect(MoreCollectors.toList(dtos.size()));
   }
 
   /**
index a2a2419102fe5ef80160e3c1908672d8faeae095..5ac77a792b72f4e6566d40aa6f97c6d3a04d6743 100644 (file)
@@ -27,7 +27,7 @@ import java.util.List;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDao;
@@ -117,7 +117,7 @@ public class PurgeDao implements Dao {
           .setStrategy(Strategy.LEAVES)
           .build())
       .stream().map(ComponentDto::uuid)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
 
     purgeCommands.deleteComponentMeasures(analysisUuids, componentWithoutHistoricalDataUuids);
   }
index 97f35d5958e488fa173f0432cc2488c01e2f3d6a..10dab8e6f454bcef2ca41b1606592484529448e7 100644 (file)
@@ -27,14 +27,14 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbSession;
 import org.sonar.db.purge.IdUuidPair;
 import org.sonar.db.purge.PurgeDao;
 import org.sonar.db.purge.PurgeProfiler;
 import org.sonar.db.purge.PurgeableAnalysisDto;
 
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class DefaultPeriodCleaner {
 
@@ -67,11 +67,11 @@ public class DefaultPeriodCleaner {
         Joiner.on(", ").join(
           snapshots.stream()
             .map(snapshot -> snapshot.getAnalysisUuid() + "@" + DateUtils.formatDateTime(snapshot.getDate()))
-            .collect(Collectors.toArrayList(snapshots.size()))));
+            .collect(MoreCollectors.toArrayList(snapshots.size()))));
     }
     purgeDao.deleteAnalyses(
       session, profiler,
-      snapshots.stream().map(DefaultPeriodCleaner::toIdUuidPair).collect(Collectors.toList(snapshots.size())));
+      snapshots.stream().map(DefaultPeriodCleaner::toIdUuidPair).collect(MoreCollectors.toList(snapshots.size())));
     return snapshots;
   }
 
index 44853151c4ca4b41cc456a65d798274f6efb596a..050043eab6a9a185891f9edfa5d2913359b7ab01 100644 (file)
@@ -30,7 +30,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.internal.TestSystem2;
 import org.sonar.core.util.CloseableIterator;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.Pagination;
@@ -381,7 +381,7 @@ public class CeActivityDaoTest {
   private List<String> selectPageOfUuids(Pagination pagination) {
     return underTest.selectByQuery(db.getSession(), new CeTaskQuery(), pagination).stream()
         .map(CeActivityToUuid.INSTANCE::apply)
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
   }
 
   private enum CeActivityToUuid implements Function<CeActivityDto, String> {
index 2df3453d9b8142492ad8c9b47d4d28c3507bb3bd..43fbcbb14fd72f566184b38e0103f27f6926741c 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.db.notification;
 
 import java.util.List;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -51,7 +51,7 @@ public class NotificationDbTester {
       .setUserId((int) userId)
       .build(), dbSession).stream()
       .filter(prop -> component == null ? prop.getResourceId() == null : prop.getResourceId() != null)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     assertThat(result).hasSize(1);
     assertThat(result.get(0).getValue()).isEqualTo("true");
   }
index c82bcdac7dec9d6236cdf361f0b234f824c76f9c..41a8bdca090fadd870c0e72e23a02535e886743e 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Optional;
 import java.util.function.Consumer;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
@@ -296,6 +296,6 @@ public class UserDbTester {
     return keys
       .stream()
       .map(OrganizationPermission::fromKey)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 }
index f36134be0d72be44d3a4a2775f9ee799d1df5a23..8d68b01bb1f31dd9c576e32f751202af1a8da490 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.db.DatabaseUtils;
 import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep;
 
 import static com.google.common.base.Preconditions.checkState;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class MigrationHistoryImpl implements MigrationHistory {
   private static final String SCHEMA_MIGRATIONS_TABLE = "schema_migrations";
index 89bbbb93d7dada161bb06c2a58799b14da4ce6e7..14065476b3049d99c389b6a1752b0b7c877b2f79 100644 (file)
@@ -29,7 +29,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.stream.Stream;
 import javax.annotation.CheckForNull;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.dialect.Dialect;
 import org.sonar.db.dialect.H2;
 import org.sonar.db.dialect.MsSql;
@@ -67,7 +67,7 @@ public class CreateTableBuilder {
     checkState(!columnDefs.isEmpty() || !pkColumnDefs.isEmpty(), "at least one column must be specified");
 
     return Stream.concat(of(createTableStatement()), createOracleAutoIncrementStatements())
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   public CreateTableBuilder addColumn(ColumnDef columnDef) {
index e04a78d48161264a3e3bb18847ba259ef949b76e..dce0c61fb8cb52fb172f34bc91cb1e2ec56593b7 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.dialect.Dialect;
 import org.sonar.db.dialect.H2;
 import org.sonar.db.dialect.MsSql;
@@ -58,7 +58,7 @@ public class DropColumnsBuilder {
       case Oracle.ID:
         return Collections.singletonList(getOracleStatement());
       case H2.ID:
-        return Arrays.stream(columns).map(this::getMsSQLStatement).collect(Collectors.toList(columns.length));
+        return Arrays.stream(columns).map(this::getMsSQLStatement).collect(MoreCollectors.toList(columns.length));
       default:
         throw new IllegalStateException(String.format("Unsupported database '%s'", dialect.getId()));
     }
index 3039819f716e4f4f2e2bb4b40de16a2366f645be..0ae8967c845d420c0f65f50e3abd3cdc2f717965 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
@@ -54,7 +54,7 @@ public class MigrationStepRegistryImpl implements InternalMigrationStepRegistry
     return migrations.entrySet().stream()
       .sorted(Comparator.comparingLong(Map.Entry::getKey))
       .map(Map.Entry::getValue)
-      .collect(Collectors.toList(migrations.size()));
+      .collect(MoreCollectors.toList(migrations.size()));
   }
 
 }
index eb74bb4992b59e69414446befb196063a7c3a4d0..43036dd037354363428b2e3a1b167146bcbb6c24 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.DatabaseUtils;
 import org.sonar.server.platform.db.migration.sql.DropTableBuilder;
 import org.sonar.server.platform.db.migration.step.DdlChange;
 
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class DropIssueFiltersTables extends DdlChange {
 
index 829b23d68d2f2bb83f82b0cb06ece37f95d60dc0..bb06b58021f7c55fd539ad3a07662bfb7ad9d1da 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.DatabaseUtils;
 import org.sonar.server.platform.db.migration.sql.DropTableBuilder;
 import org.sonar.server.platform.db.migration.step.DdlChange;
 
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class DropMeasureFiltersTables extends DdlChange {
 
index 3c1236c722d930710069669f818b4fda4bf13755..ad7e563422e4c083d454e78ab5f7ee6b4437250c 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.DatabaseUtils;
 import org.sonar.server.platform.db.migration.sql.DropTableBuilder;
 import org.sonar.server.platform.db.migration.step.DdlChange;
 
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class DropRelatedDashboardTables extends DdlChange {
 
index 77f996be513d9a06a2485161abf9b1fd5a19c7c1..91ddc1d5105d1c0e32873f2df5228015ed7864df 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.server.platform.db.migration.step.DataChange;
 import org.sonar.server.platform.db.migration.step.Select;
 
 import static java.util.Objects.requireNonNull;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.db.DatabaseUtils.repeatCondition;
 
 /**
index 444aae7628ce19cfaa31cc710523a1e3ca3861e9..b0c6bcd47a324a7cd4380e327a23d6cd63949903 100644 (file)
@@ -26,7 +26,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -76,7 +76,7 @@ public class PopulateInitialSchemaTest {
       "from group_roles gr where gr.group_id is null");
     List<String> roles = rows.stream()
       .map(row -> (String) row.get("role"))
-      .collect(Collectors.toArrayList());
+      .collect(MoreCollectors.toArrayList());
     assertThat(roles).containsOnly("provisioning", "scan");
   }
 
@@ -87,7 +87,7 @@ public class PopulateInitialSchemaTest {
       "where g.name='" + groupName + "'");
     return rows.stream()
       .map(row -> (String) row.get("role"))
-      .collect(Collectors.toArrayList());
+      .collect(MoreCollectors.toArrayList());
   }
 
   private void verifyGroup(String expectedName, String expectedDescription) {
@@ -106,7 +106,7 @@ public class PopulateInitialSchemaTest {
       "where u.login='admin'");
     List<String> groupNames = rows.stream()
       .map(row -> (String) row.get("groupName"))
-      .collect(Collectors.toArrayList());
+      .collect(MoreCollectors.toArrayList());
     assertThat(groupNames).containsOnly("sonar-administrators", "sonar-users");
   }
 
index ecb13741cafade60080d02ae253d63c6f90bbe68..4b8df9f7af9270a6b4b4512b8940a22e88e5026c 100644 (file)
@@ -30,7 +30,7 @@ import org.apache.commons.lang.RandomStringUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.CoreDbTester;
 import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidImpl;
 
@@ -305,7 +305,7 @@ public class PopulateOrganizationMembersTableTest {
     List<Map<String, Object>> rows = db.select(format("SELECT ORGANIZATION_UUID FROM " + TABLE + " WHERE USER_ID = %s", userId));
     List<String> userOrganizationUuids = rows.stream()
       .map(values -> (String) values.get("ORGANIZATION_UUID"))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     assertThat(userOrganizationUuids).containsOnly(organizationUuids);
   }
 
index 82168dc834c60c05ac8d8711ce01cb3a1296d9a3..ad9e426328a9e768d9f45d8390f0824bcb74c149 100644 (file)
@@ -30,7 +30,7 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.CoreDbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -167,12 +167,12 @@ public class SetCopyComponentUuidOnLocalViewsTest {
   }
 
   private void verifyComponentsHavingCopyComponentUuid(Component... expectedComponents) {
-    Map<String, Component> expectedComponentsByUuid = Arrays.stream(expectedComponents).collect(Collectors.uniqueIndex(Component::getUuid));
+    Map<String, Component> expectedComponentsByUuid = Arrays.stream(expectedComponents).collect(MoreCollectors.uniqueIndex(Component::getUuid));
 
     List<Map<String, Object>> rows = db.select("SELECT uuid, copy_component_uuid FROM " + TABLE_PROJECTS + " WHERE copy_component_uuid IS NOT NULL");
     Map<String, Component> components = rows.stream()
       .map(map -> new Component((String) map.get("UUID"), (String) map.get("COPY_COMPONENT_UUID")))
-      .collect(Collectors.uniqueIndex(Component::getUuid));
+      .collect(MoreCollectors.uniqueIndex(Component::getUuid));
     assertThat(components.keySet()).containsExactlyElementsOf(expectedComponentsByUuid.keySet());
     components.entrySet().forEach(entry -> {
       Component expectedComponent = expectedComponentsByUuid.get(entry.getKey());
index d679ac9c78396e5bb1eb378d36b8a4f08239aebf..04c89c7100350bcf37b49fb1764031aaaddbcbe6 100644 (file)
@@ -46,7 +46,7 @@ import org.sonar.server.user.UserUpdater;
 
 import static java.lang.String.format;
 import static java.util.Collections.singletonList;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 
 public class UserIdentityAuthenticator {
 
index 58dbd939f863ed5f9fdccd329080e628aeeb3105..32cdebc2ad9de4b9f5c33779a8c2a281662f07ae 100644 (file)
@@ -25,7 +25,7 @@ import javax.annotation.Nullable;
 import javax.servlet.http.HttpServletRequest;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static java.util.Objects.requireNonNull;
 
@@ -47,7 +47,7 @@ public class AuthenticationEventImpl implements AuthenticationEvent {
   }
 
   private static String getAllIps(HttpServletRequest request) {
-    return Collections.list(request.getHeaders("X-Forwarded-For")).stream().collect(Collectors.join(Joiner.on(",")));
+    return Collections.list(request.getHeaders("X-Forwarded-For")).stream().collect(MoreCollectors.join(Joiner.on(",")));
   }
 
   @Override
index 799c722fbe0d1dd909469bcf69d2e43888fe29fc..fdc082607ed623abc8ddb144364abe163d7c9bd7 100644 (file)
@@ -32,7 +32,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.core.util.Uuids;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.ce.CeActivityDto;
@@ -173,13 +173,13 @@ public class TaskAction implements CeWsAction {
           return null;
         })
         .filter(Objects::nonNull)
-        .collect(Collectors.toSet());
+        .collect(MoreCollectors.toSet());
     }
 
     public static Collection<String> possibleValues() {
       return Arrays.stream(values())
         .map(AdditionalField::getLabel)
-        .collect(Collectors.toList(values().length));
+        .collect(MoreCollectors.toList(values().length));
     }
   }
 }
index 245c551121a62d3793196e3eb3cf5ab90e4612e9..c71d472597a688737adf81c64fa90c8665f0c5a3 100644 (file)
@@ -31,7 +31,7 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.ce.CeActivityDto;
@@ -62,7 +62,7 @@ public class TaskFormatter {
 
   public List<WsCe.Task> formatQueue(DbSession dbSession, List<CeQueueDto> dtos) {
     ComponentDtoCache cache = ComponentDtoCache.forQueueDtos(dbClient, dbSession, dtos);
-    return dtos.stream().map(input -> formatQueue(input, cache)).collect(Collectors.toList(dtos.size()));
+    return dtos.stream().map(input -> formatQueue(input, cache)).collect(MoreCollectors.toList(dtos.size()));
   }
 
   public WsCe.Task formatQueue(DbSession dbSession, CeQueueDto dto) {
@@ -107,7 +107,7 @@ public class TaskFormatter {
     ComponentDtoCache cache = ComponentDtoCache.forActivityDtos(dbClient, dbSession, dtos);
     return dtos.stream()
       .map(input -> formatActivity(input, cache, null))
-      .collect(Collectors.toList(dtos.size()));
+      .collect(MoreCollectors.toList(dtos.size()));
   }
 
   private static WsCe.Task formatActivity(CeActivityDto dto, ComponentDtoCache componentDtoCache, @Nullable String scannerContext) {
@@ -156,7 +156,7 @@ public class TaskFormatter {
     static ComponentDtoCache forQueueDtos(DbClient dbClient, DbSession dbSession, Collection<CeQueueDto> ceQueueDtos) {
       Map<String, ComponentDto> componentsByUuid = dbClient.componentDao().selectByUuids(dbSession, uuidOfCeQueueDtos(ceQueueDtos))
         .stream()
-        .collect(Collectors.uniqueIndex(ComponentDto::uuid));
+        .collect(MoreCollectors.uniqueIndex(ComponentDto::uuid));
       return new ComponentDtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid));
     }
 
@@ -165,7 +165,7 @@ public class TaskFormatter {
         .filter(Objects::nonNull)
         .map(CeQueueDto::getComponentUuid)
         .filter(Objects::nonNull)
-        .collect(Collectors.toSet(ceQueueDtos.size()));
+        .collect(MoreCollectors.toSet(ceQueueDtos.size()));
     }
 
     static ComponentDtoCache forActivityDtos(DbClient dbClient, DbSession dbSession, Collection<CeActivityDto> ceActivityDtos) {
@@ -173,7 +173,7 @@ public class TaskFormatter {
         dbSession,
         uuidOfCeActivityDtos(ceActivityDtos))
         .stream()
-        .collect(Collectors.uniqueIndex(ComponentDto::uuid));
+        .collect(MoreCollectors.uniqueIndex(ComponentDto::uuid));
       return new ComponentDtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid));
     }
 
@@ -182,7 +182,7 @@ public class TaskFormatter {
         .filter(Objects::nonNull)
         .map(CeActivityDto::getComponentUuid)
         .filter(Objects::nonNull)
-        .collect(Collectors.toSet(ceActivityDtos.size()));
+        .collect(MoreCollectors.toSet(ceActivityDtos.size()));
     }
 
     static ComponentDtoCache forUuid(DbClient dbClient, DbSession dbSession, String uuid) {
@@ -200,9 +200,9 @@ public class TaskFormatter {
         dbSession,
         componentsByUuid.values().stream()
           .map(ComponentDto::getOrganizationUuid)
-          .collect(Collectors.toSet(componentsByUuid.size())))
+          .collect(MoreCollectors.toSet(componentsByUuid.size())))
         .stream()
-        .collect(Collectors.uniqueIndex(OrganizationDto::getUuid));
+        .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid));
     }
 
     @CheckForNull
index b4dc747d2425e273e3b17a28528b54b27446d0b6..1054150c3d632c4d8fa6f1f5e3c398e6810099d2 100644 (file)
@@ -25,7 +25,7 @@ import javax.annotation.Nullable;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypes;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -92,7 +92,7 @@ public class ComponentFinder {
     Set<String> rootQualifiers = rootTypes
       .stream()
       .map(ResourceType::getQualifier)
-      .collect(Collectors.toSet(rootTypes.size()));
+      .collect(MoreCollectors.toSet(rootTypes.size()));
     String qualifier = component.qualifier();
 
     checkRequest(rootQualifiers.contains(qualifier) || Qualifiers.MODULE.equals(qualifier),
index 4d9f7af46f0891e8387a0c4464b109adfaabba81..47564f4d88961e65d3eb94b7eac893bee7f1cced 100644 (file)
@@ -36,7 +36,7 @@ import org.elasticsearch.search.aggregations.bucket.filters.InternalFilters;
 import org.elasticsearch.search.aggregations.bucket.filters.InternalFilters.Bucket;
 import org.elasticsearch.search.aggregations.metrics.tophits.InternalTopHits;
 import org.elasticsearch.search.aggregations.metrics.tophits.TopHitsBuilder;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.es.EsClient;
 import org.sonar.server.es.textsearch.ComponentTextSearchFeature;
 import org.sonar.server.es.textsearch.ComponentTextSearchQueryFactory;
@@ -116,7 +116,7 @@ public class ComponentIndex {
     List<Bucket> buckets = filtersAgg.getBuckets();
     return buckets.stream()
       .map(ComponentIndex::bucketToQualifier)
-      .collect(Collectors.toList(buckets.size()));
+      .collect(MoreCollectors.toList(buckets.size()));
   }
 
   private static ComponentsPerQualifier bucketToQualifier(Bucket bucket) {
@@ -126,7 +126,7 @@ public class ComponentIndex {
     SearchHit[] hits = hitList.getHits();
 
     List<String> componentUuids = Arrays.stream(hits).map(SearchHit::getId)
-      .collect(Collectors.toList(hits.length));
+      .collect(MoreCollectors.toList(hits.length));
 
     return new ComponentsPerQualifier(bucket.getKey(), componentUuids, hitList.totalHits());
   }
index 9a4a3f0219b7823916e6f4910800e70d325e16eb..04c4852f4194e99215dbfd6ff64cf94e03d20456 100644 (file)
@@ -27,7 +27,7 @@ import java.util.regex.Pattern;
 import java.util.stream.StreamSupport;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static java.lang.String.format;
@@ -51,7 +51,7 @@ public class FilterParser {
   public static List<Criterion> parse(String filter) {
     return StreamSupport.stream(CRITERIA_SPLITTER.split(filter).spliterator(), false)
       .map(FilterParser::parseCriterion)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   private static Criterion parseCriterion(String rawCriterion) {
index 51118a13380cb88b49e3c0d4e4804530049732d4..414cc70770a486061f1fefdc2feddedff219c86a 100644 (file)
@@ -29,8 +29,8 @@ import org.sonar.db.metric.MetricDto;
 import org.sonar.server.measure.index.ProjectMeasuresQuery;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.core.util.stream.Collectors.toHashSet;
-import static org.sonar.core.util.stream.Collectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.toHashSet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 import static org.sonar.server.measure.index.ProjectMeasuresQuery.MetricCriterion;
 import static org.sonar.server.measure.index.ProjectMeasuresQuery.SORT_BY_NAME;
 
index d9a9dd48a013d8e2dd30e448a3aae2319c226ab3..5c57fbb2f66eb1a922ea40887c1227ea8137addb 100644 (file)
@@ -32,7 +32,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.Paging;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -48,7 +48,7 @@ import org.sonarqube.ws.client.component.SearchWsRequest;
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.util.LanguageParamUtils.getExampleValue;
 import static org.sonar.server.util.LanguageParamUtils.getLanguageKeys;
 import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter;
@@ -166,13 +166,13 @@ public class SearchAction implements ComponentsWsAction {
       // Meanwhile root is explicitly handled.
       return componentDtos;
     }
-    Set<String> projectUuids = componentDtos.stream().map(ComponentDto::projectUuid).collect(Collectors.toSet());
+    Set<String> projectUuids = componentDtos.stream().map(ComponentDto::projectUuid).collect(MoreCollectors.toSet());
     List<ComponentDto> projects = dbClient.componentDao().selectByUuids(dbSession, projectUuids);
     Map<String, Long> projectIdsByUuids = projects.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
     Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession, projectIdsByUuids.values(), userSession.getUserId(), USER);
     return componentDtos.stream()
       .filter(component -> authorizedProjectIds.contains(projectIdsByUuids.get(component.projectUuid())))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   private static SearchWsResponse buildResponse(List<ComponentDto> components, OrganizationDto organization, Paging paging) {
index fd148a031f9fc3d145c1cdb33b91d786d7b0b2e0..f4d28bf183ea261ed9fa656627a8b9572d46798a 100644 (file)
@@ -39,7 +39,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.DateUtils;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -67,7 +67,7 @@ import static java.util.Collections.emptyMap;
 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
 import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
 import static org.sonar.api.server.ws.WebService.Param.FIELDS;
-import static org.sonar.core.util.stream.Collectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.IS_FAVORITE_CRITERION;
 import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.newProjectMeasuresQuery;
 import static org.sonar.server.measure.index.ProjectMeasuresIndex.SUPPORTED_FACETS;
@@ -201,7 +201,7 @@ public class SearchProjectsAction implements ComponentsWsAction {
     Set<String> organizationUuids = searchResults.projects.stream().map(ComponentDto::getOrganizationUuid).collect(toSet());
     Map<String, OrganizationDto> organizationsByUuid = dbClient.organizationDao().selectByUuids(dbSession, organizationUuids)
       .stream()
-      .collect(Collectors.uniqueIndex(OrganizationDto::getUuid));
+      .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid));
     return buildResponse(request, searchResults, organizationsByUuid);
   }
 
@@ -253,20 +253,20 @@ public class SearchProjectsAction implements ComponentsWsAction {
 
     List<Long> favoriteDbIds = props.stream()
       .map(PropertyDto::getResourceId)
-      .collect(Collectors.toList(props.size()));
+      .collect(MoreCollectors.toList(props.size()));
 
     return dbClient.componentDao().selectByIds(dbSession, favoriteDbIds).stream()
       .filter(ComponentDto::isEnabled)
       .filter(f -> f.qualifier().equals(Qualifiers.PROJECT))
       .map(ComponentDto::uuid)
-      .collect(Collectors.toSet());
+      .collect(MoreCollectors.toSet());
   }
 
   private Map<String, SnapshotDto> getSnapshots(DbSession dbSession, SearchProjectsRequest request, List<String> projectUuids) {
     if (request.getAdditionalFields().contains(ANALYSIS_DATE)) {
       return dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids)
         .stream()
-        .collect(Collectors.uniqueIndex(SnapshotDto::getComponentUuid));
+        .collect(MoreCollectors.uniqueIndex(SnapshotDto::getComponentUuid));
     }
     return emptyMap();
   }
index efc9671ebc0e87dedac51abf63eec9a7a0fc68b9..37801d9220509819ff2c3559d1677782b03c8927 100644 (file)
@@ -30,7 +30,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.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -124,13 +124,13 @@ public class SuggestionsAction implements ComponentsWsAction {
         List<Component> results = sortedComponentDtos
           .stream()
           .map(dto -> dtoToComponent(dto, organizationKeyByUuids))
-          .collect(Collectors.toList());
+          .collect(MoreCollectors.toList());
 
         return Qualifier.newBuilder()
           .setQ(qualifier.getQualifier())
           .addAllItems(results)
           .build();
-      }).collect(Collectors.toList());
+      }).collect(MoreCollectors.toList());
     }
 
   }
@@ -138,9 +138,9 @@ public class SuggestionsAction implements ComponentsWsAction {
   private Map<String, String> getOrganizationKeys(DbSession dbSession, List<ComponentDto> componentDtos) {
     return dbClient.organizationDao().selectByUuids(
       dbSession,
-      componentDtos.stream().map(ComponentDto::getOrganizationUuid).collect(Collectors.toSet()))
+      componentDtos.stream().map(ComponentDto::getOrganizationUuid).collect(MoreCollectors.toSet()))
       .stream()
-      .collect(Collectors.uniqueIndex(OrganizationDto::getUuid, OrganizationDto::getKey));
+      .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid, OrganizationDto::getKey));
   }
 
   private List<ComponentsPerQualifier> searchInIndex(ComponentIndexQuery componentIndexQuery) {
index c5b0a8254cf4486a8e7c674398f5d22930382723..aa67d804a534aaffd5a1f6415cca915b927d015a 100644 (file)
@@ -40,7 +40,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.Paging;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -186,13 +186,13 @@ public class TreeAction implements ComponentsWsAction {
     List<String> referenceComponentIds = components.stream()
       .map(ComponentDto::getCopyResourceUuid)
       .filter(Objects::nonNull)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     if (referenceComponentIds.isEmpty()) {
       return emptyMap();
     }
 
     return dbClient.componentDao().selectByUuids(dbSession, referenceComponentIds).stream()
-      .collect(Collectors.uniqueIndex(ComponentDto::uuid));
+      .collect(MoreCollectors.uniqueIndex(ComponentDto::uuid));
   }
 
   private void checkPermissions(ComponentDto baseComponent) {
index e709736e56d45ef42b63468f60258a9da9cdbdf9..1621fadc1771d74fa8841b1d8ad6ac34b518519b 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.platform.ServerStartHandler;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.ce.CeActivityDto;
@@ -56,7 +56,7 @@ public class PurgeCeActivities implements ServerStartHandler {
       Set<String> ceActivityUuids = dbClient.ceActivityDao().selectOlderThan(dbSession, sixMonthsAgo.getTimeInMillis())
         .stream()
         .map(CeActivityDto::getUuid)
-        .collect(Collectors.toSet());
+        .collect(MoreCollectors.toSet());
       dbClient.ceActivityDao().deleteByUuids(dbSession, ceActivityUuids);
       dbClient.ceScannerContextDao().deleteByUuids(dbSession, ceActivityUuids);
       dbSession.commit();
index 8bb9554698b008e8c55a447c4aa542a11e94df24..ab731524c0286dfc72ff4a5766e761d6248c6e9d 100644 (file)
@@ -36,7 +36,7 @@ import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.trimToNull;
 import static org.sonar.core.component.ComponentKeys.createEffectiveKey;
 import static org.sonar.core.component.ComponentKeys.createKey;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class ComponentRootBuilder {
   private static final String DEFAULT_PROJECT_VERSION = "not provided";
index a9b4ee85bc4feafbca5251ceac5234121f8b78e6..a524141097cde5e799a78ecbc43a35001b6e79bf 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.computation.task.projectanalysis.qualitygate;
 
 import com.google.common.base.Optional;
 import java.util.Collection;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
@@ -58,7 +58,7 @@ public class QualityGateServiceImpl implements QualityGateService {
         Metric metric = metricRepository.getById(input.getMetricId());
         return new Condition(metric, input.getOperator(), input.getErrorThreshold(), input.getWarningThreshold(), input.getPeriod() != null);
       })
-      .collect(Collectors.toList(dtos.size()));
+      .collect(MoreCollectors.toList(dtos.size()));
 
     return new QualityGate(qualityGateDto.getId(), qualityGateDto.getName(), conditions);
   }
index 5f14e0e06b2d5e0182dc9b3f9db622cefd5ce91c..64c958d0dc6057dfaec173f9988179bdf61d22af 100644 (file)
@@ -29,7 +29,7 @@ import java.util.stream.StreamSupport;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.protobuf.DbFileSources;
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 
@@ -52,7 +52,7 @@ class DbScmInfo implements ScmInfo {
     List<Changeset> lineChangesets = StreamSupport.stream(lines.spliterator(), false)
       .map(lineToChangeset)
       .filter(Objects::nonNull)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     if (lineChangesets.isEmpty()) {
       return Optional.absent();
     }
index 074fc983bf4cbb59d51d45ab7f45aa6e03d10841..7bb05b4f25e38f10ca597dcb9d9e7ca9a4f8c5eb 100644 (file)
@@ -29,7 +29,7 @@ import java.util.function.Predicate;
 import java.util.stream.StreamSupport;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.measure.PastMeasureDto;
@@ -50,7 +50,7 @@ import org.sonar.server.computation.task.step.ComputationStep;
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.lang.String.format;
 import static java.util.function.Function.identity;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.DIRECTORY;
 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.SUBVIEW;
 import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
@@ -81,7 +81,7 @@ public class ComputeMeasureVariationsStep implements ComputationStep {
   @Override
   public void execute() {
     try (DbSession dbSession = dbClient.openSession(false)) {
-      List<Metric> metrics = StreamSupport.stream(metricRepository.getAll().spliterator(), false).filter(isNumeric()).collect(Collectors.toList());
+      List<Metric> metrics = StreamSupport.stream(metricRepository.getAll().spliterator(), false).filter(isNumeric()).collect(MoreCollectors.toList());
       new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics))
         .visit(treeRootHolder.getRoot());
     }
@@ -97,7 +97,7 @@ public class ComputeMeasureVariationsStep implements ComputationStep {
       // measures on files are currently purged, so past measures are not available on files
       super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER);
       this.session = session;
-      this.metricIds = metrics.stream().map(Metric::getId).collect(Collectors.toSet());
+      this.metricIds = metrics.stream().map(Metric::getId).collect(MoreCollectors.toSet());
       this.metrics = metrics;
     }
 
index 9fc337e94536d8d5bb772f47b785d5cd8de5300f..fd8f7cb451d54c2528c45406b43d0f309e691058 100644 (file)
@@ -27,7 +27,7 @@ import java.util.Optional;
 import javax.annotation.Nullable;
 import org.sonar.api.utils.MessageException;
 import org.sonar.ce.queue.CeTask;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -45,7 +45,7 @@ import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Maps.transformValues;
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.isNotEmpty;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 /**
  * Feed analysis metadata holder with metadata from the analysis report.
@@ -105,7 +105,7 @@ public class LoadReportAnalysisMetadataHolderStep implements ComputationStep {
       String badKeys = profiles.stream()
         .filter(p -> !p.getOrganizationUuid().equals(organization.getUuid()))
         .map(QualityProfileDto::getKey)
-        .collect(Collectors.join(Joiner.on(", ")));
+        .collect(MoreCollectors.join(Joiner.on(", ")));
       if (!badKeys.isEmpty()) {
         throw MessageException.of(format("Quality profiles with following keys don't exist in organization [%s]: %s", organization.getKey(), badKeys));
       }
index 6d793c70f9e63eaf2c377f973f2a6941c710ba02..c32afa645098a4a4517558c65aae37a5ba5a7a84 100644 (file)
@@ -32,7 +32,7 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -107,7 +107,7 @@ public class PersistComponentsStep implements ComputationStep {
     Set<String> uuids = dtos.stream()
       .filter(ComponentDto::isEnabled)
       .map(ComponentDto::uuid)
-      .collect(Collectors.toSet(dtos.size()));
+      .collect(MoreCollectors.toSet(dtos.size()));
     dbClient.componentDao().updateBEnabledToFalse(dbSession, uuids);
     disabledComponentsHolder.setUuids(uuids);
   }
index cbae46ada60f7441f21714073ce07e6f3eb1b7d0..97a355feca710b0a4a677833d9687d0cf583abec 100644 (file)
@@ -33,7 +33,7 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.computation.task.projectanalysis.component.Component;
 import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
 import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
@@ -171,7 +171,7 @@ public class QualityGateMeasuresStep implements ComputationStep {
   }
 
   private void updateMeasures(Component project, Set<Condition> conditions, QualityGateDetailsDataBuilder builder) {
-    Multimap<Metric, Condition> conditionsPerMetric = conditions.stream().collect(Collectors.index(Condition::getMetric, java.util.function.Function.identity()));
+    Multimap<Metric, Condition> conditionsPerMetric = conditions.stream().collect(MoreCollectors.index(Condition::getMetric, java.util.function.Function.identity()));
     for (Map.Entry<Metric, Collection<Condition>> entry : conditionsPerMetric.asMap().entrySet()) {
       Metric metric = entry.getKey();
       Optional<Measure> measure = measureRepository.getRawMeasure(project, metric);
index 5dbae13a8c9c11b10b0ccac84586161422ef8e38..6baef99868a5197ef20da5011060661385526f56 100644 (file)
@@ -28,7 +28,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.core.config.WebhookProperties;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.computation.task.projectanalysis.component.SettingsRepository;
 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
 
@@ -72,7 +72,7 @@ public class WebhookPostTask implements PostProjectAnalysisTask {
     return Arrays.stream(webhookIds)
       .map(webhookId -> format("%s.%s", propertyKey, webhookId))
       .limit(MAX_WEBHOOKS_PER_TYPE)
-      .collect(Collectors.toList(webhookIds.length));
+      .collect(MoreCollectors.toList(webhookIds.length));
   }
 
   private void process(Settings settings, ProjectAnalysis analysis, Iterable<String> webhookProperties) {
index 537354afe322c3ea0c2713114fd6ee8beea47078..22e263428ce755b74d68481026466ff0fefe9afa 100644 (file)
@@ -41,7 +41,7 @@ import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.SearchHits;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
 import org.joda.time.format.ISODateTimeFormat;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static java.lang.String.format;
 
@@ -78,7 +78,7 @@ public class EsUtils {
   public static List<String> termsKeys(Terms terms) {
     return terms.getBuckets().stream()
       .map(Terms.Bucket::getKeyAsString)
-      .collect(Collectors.toList(terms.getBuckets().size()));
+      .collect(MoreCollectors.toList(terms.getBuckets().size()));
   }
 
 
index cb61216cd84b6a5d677aa8d0ddb02e96819baf01..4ead86465ef7fddfc87cd8e36da70aa770297b4d 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.es;
 
 import java.util.Arrays;
 import java.util.function.Function;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static java.util.Objects.requireNonNull;
 
@@ -52,7 +52,7 @@ public class IndexType {
   }
 
   private static String[] getDetails(Function<? super IndexType, ? extends String> function, IndexType... indexTypes) {
-    return Arrays.stream(indexTypes).map(function).collect(Collectors.toSet(indexTypes.length)).toArray(new String[0]);
+    return Arrays.stream(indexTypes).map(function).collect(MoreCollectors.toSet(indexTypes.length)).toArray(new String[0]);
   }
 
   @Override
index b3c177274e3b8f3c266f31d9ffe10fb49ad8c505..b2bb23b0482ee01936de2ee0e8acac67ae97f79b 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.db.property.PropertyQuery;
 import org.sonar.server.user.UserSession;
 
 import static java.util.Collections.emptyList;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 import static org.sonar.server.favorite.FavoriteUpdater.PROP_FAVORITE_KEY;
 
 public class FavoriteFinder {
index 950da42af2fbf846141cb50e976b93085f0d385b..b94c6470baa83f4486508ed5967b3f01defbfb33 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.Paging;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -90,12 +90,12 @@ public class SearchAction implements FavoritesWsAction {
     try (DbSession dbSession = dbClient.openSession(false)) {
       List<ComponentDto> authorizedFavorites = favoriteFinder.list().stream()
         .filter(isAuthorized(dbSession))
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
       Paging paging = Paging.forPageIndex(request.getPage()).withPageSize(request.getPageSize()).andTotal(authorizedFavorites.size());
       List<ComponentDto> displayedFavorites = authorizedFavorites.stream()
         .skip(paging.offset())
         .limit(paging.pageSize())
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
       Map<String, OrganizationDto> organizationsByUuid = getOrganizationsOfComponents(dbSession, displayedFavorites);
       return new SearchResults(paging, displayedFavorites, organizationsByUuid);
     }
@@ -105,17 +105,17 @@ public class SearchAction implements FavoritesWsAction {
     Collection<String> rootProjectsUuids = dbClient.authorizationDao().selectAuthorizedRootProjectsUuids(dbSession, userSession.getUserId(), UserRole.USER);
     Set<String> authorizedProjectUuids = rootProjectsUuids
       .stream()
-      .collect(Collectors.toSet(rootProjectsUuids.size()));
+      .collect(MoreCollectors.toSet(rootProjectsUuids.size()));
     return dto -> authorizedProjectUuids.contains(dto.projectUuid());
   }
 
   private Map<String, OrganizationDto> getOrganizationsOfComponents(DbSession dbSession, List<ComponentDto> displayedFavorites) {
     Set<String> organizationUuids = displayedFavorites.stream()
         .map(ComponentDto::getOrganizationUuid)
-        .collect(Collectors.toSet());
+        .collect(MoreCollectors.toSet());
     return dbClient.organizationDao().selectByUuids(dbSession, organizationUuids)
         .stream()
-        .collect(Collectors.uniqueIndex(OrganizationDto::getUuid));
+        .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid));
   }
 
   private static class SearchResults {
index 2a2b2434c473da8faa75b03e88138809c46b0581..725d93d036a27fb160588a0738bbaa1433ea90a3 100644 (file)
@@ -37,7 +37,7 @@ import org.sonar.api.utils.Duration;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.issue.DefaultIssueComment;
 import org.sonar.core.issue.IssueChangeContext;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.user.UserDto;
 
 import static com.google.common.base.Preconditions.checkState;
@@ -316,7 +316,7 @@ public class IssueFieldsSetter {
       .filter(Objects::nonNull)
       .filter(tag -> !tag.isEmpty())
       .map(tag -> RuleTagFormat.validate(tag.toLowerCase(Locale.ENGLISH)))
-      .collect(Collectors.toSet());
+      .collect(MoreCollectors.toSet());
 
     Set<String> oldTags = Sets.newHashSet(issue.tags());
     if (!oldTags.equals(newTags)) {
index 1d18c7731f81db0128d6267120b8e50104bee121..43f8cbedae08ee6eecc0a809a8e4b43f35b83dad 100644 (file)
@@ -45,7 +45,7 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -283,7 +283,7 @@ public class IssueQueryFactory {
       return;
     }
 
-    Set<String> qualifiers = components.stream().map(ComponentDto::qualifier).collect(Collectors.toHashSet());
+    Set<String> qualifiers = components.stream().map(ComponentDto::qualifier).collect(MoreCollectors.toHashSet());
     if (qualifiers.size() > 1) {
       throw new IllegalArgumentException("All components must have the same qualifier, found " + Joiner.on(',').join(qualifiers));
     }
@@ -337,7 +337,7 @@ public class IssueQueryFactory {
   }
 
   private Collection<String> convertComponentKeysToUuids(DbSession dbSession, Collection<String> componentKeys) {
-    List<String> componentUuids = dbClient.componentDao().selectByKeys(dbSession, componentKeys).stream().map(ComponentDto::uuid).collect(Collectors.toList());
+    List<String> componentUuids = dbClient.componentDao().selectByKeys(dbSession, componentKeys).stream().map(ComponentDto::uuid).collect(MoreCollectors.toList());
     // If unknown components are given, but no components are found, then all issues will be returned,
     // so we add this hack in order to return no issue in this case.
     if (!componentKeys.isEmpty() && componentUuids.isEmpty()) {
index c0c57be6a598252a716740b6af16241c6cca4f73..d88c80aedb206bdcb23b4d4132086291217dea49 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Collection;
 import java.util.Map;
 import org.sonar.api.server.ServerSide;
 import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.issue.workflow.Transition;
 import org.sonar.server.user.UserSession;
 
@@ -60,7 +60,7 @@ public class TransitionAction extends Action {
     return transitionService.listTransitions(issue)
       .stream()
       .map(Transition::key)
-      .collect(Collectors.toSet())
+      .collect(MoreCollectors.toSet())
       .contains(transitionKey);
   }
 
index ce29c8ebf956df4adc412d158d0964499dd8b7ee..7a441c1e4a351893d45a339a6bc6f9c455ba0e3e 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.issue;
 import java.util.List;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.issue.IssueChangeContext;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.issue.workflow.IssueWorkflow;
 import org.sonar.server.issue.workflow.Transition;
 import org.sonar.server.user.UserSession;
@@ -50,7 +50,7 @@ public class TransitionService {
       .stream()
       .filter(transition -> (userSession.isLoggedIn() && isBlank(transition.requiredProjectPermission()))
         || userSession.hasComponentUuidPermission(transition.requiredProjectPermission(), projectUuid))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   public boolean doTransition(DefaultIssue defaultIssue, IssueChangeContext issueChangeContext, String transitionKey) {
index a97346655d4e59585c4668c33008f5c6a5502a5d..0f1c7d06d56f90caecdf68a00ee5d3d64626c578 100644 (file)
@@ -65,7 +65,7 @@ import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.NonNullInputFunction;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.server.es.EsClient;
 import org.sonar.server.es.EsUtils;
@@ -529,7 +529,7 @@ public class IssueIndex {
     if (values == null) {
       return Collections.emptyList();
     }
-    return values.stream().map(Pattern::quote).collect(Collectors.toArrayList(values.size()));
+    return values.stream().map(Pattern::quote).collect(MoreCollectors.toArrayList(values.size()));
   }
 
   private void addAssignedToMeFacetIfNeeded(SearchRequestBuilder builder, SearchOptions options, IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
index 4ca1f97cb40fbe3bd9a8df8f8d5db239ee25f371..dc51adcc989af40a1bae941e0c49b74ab85bd08e 100644 (file)
@@ -45,7 +45,7 @@ import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.issue.IssueChangeContext;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -70,8 +70,8 @@ import static org.sonar.api.rule.Severity.BLOCKER;
 import static org.sonar.api.rules.RuleType.BUG;
 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
-import static org.sonar.core.util.stream.Collectors.toList;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
 import static org.sonar.server.issue.AbstractChangeTagsAction.TAGS_PARAMETER;
 import static org.sonar.server.issue.AssignAction.ASSIGNEE_PARAMETER;
@@ -184,7 +184,7 @@ public class BulkChangeAction implements IssuesWsAction {
         .map(loadData(dbSession))
         .map(executeBulkChange())
         .map(toWsResponse())
-        .collect(Collectors.toOneElement());
+        .collect(MoreCollectors.toOneElement());
       writeProtobuf(wsResponse, request, response);
     }
   }
@@ -200,7 +200,7 @@ public class BulkChangeAction implements IssuesWsAction {
 
       List<DefaultIssue> items = bulkChangeData.issues.stream()
         .filter(bulkChange(issueChangeContext, bulkChangeData, result))
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
       issueStorage.save(items);
       items.forEach(sendNotification(issueChangeContext, bulkChangeData));
       return result;
@@ -301,20 +301,20 @@ public class BulkChangeAction implements IssuesWsAction {
       checkArgument(issueKeys.size() <= MAX_LIMIT, "Number of issues is limited to %s", MAX_LIMIT);
       List<IssueDto> allIssues = dbClient.issueDao().selectByKeys(dbSession, issueKeys);
 
-      List<ComponentDto> allProjects = getComponents(dbSession, allIssues.stream().map(IssueDto::getProjectUuid).collect(Collectors.toSet()));
+      List<ComponentDto> allProjects = getComponents(dbSession, allIssues.stream().map(IssueDto::getProjectUuid).collect(MoreCollectors.toSet()));
       this.projectsByUuid = getAuthorizedProjects(dbSession, allProjects).stream().collect(uniqueIndex(ComponentDto::uuid, identity()));
       this.issues = getAuthorizedIssues(allIssues);
       this.componentsByUuid = getComponents(dbSession,
-        issues.stream().map(DefaultIssue::componentUuid).collect(Collectors.toSet())).stream()
+        issues.stream().map(DefaultIssue::componentUuid).collect(MoreCollectors.toSet())).stream()
           .collect(uniqueIndex(ComponentDto::uuid, identity()));
       this.rulesByKey = dbClient.ruleDao().selectDefinitionByKeys(dbSession,
-        issues.stream().map(DefaultIssue::ruleKey).collect(Collectors.toSet())).stream()
+        issues.stream().map(DefaultIssue::ruleKey).collect(MoreCollectors.toSet())).stream()
         .collect(uniqueIndex(RuleDefinitionDto::getKey, identity()));
 
       this.availableActions = actions.stream()
         .filter(action -> propertiesByActions.containsKey(action.key()))
         .filter(action -> action.verify(getProperties(action.key()), issues, userSession))
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
     }
 
     private List<ComponentDto> getComponents(DbSession dbSession, Collection<String> componentUuids) {
@@ -328,15 +328,15 @@ public class BulkChangeAction implements IssuesWsAction {
         userSession.getUserId(), UserRole.USER);
       return projectDtos.stream()
         .filter(project -> authorizedProjectIds.contains(projectIdsByUuids.get(project.projectUuid())))
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
     }
 
     private List<DefaultIssue> getAuthorizedIssues(List<IssueDto> allIssues) {
-      Set<String> projectUuids = projectsByUuid.values().stream().map(ComponentDto::uuid).collect(Collectors.toSet());
+      Set<String> projectUuids = projectsByUuid.values().stream().map(ComponentDto::uuid).collect(MoreCollectors.toSet());
       return allIssues.stream()
         .filter(issue -> projectUuids.contains(issue.getProjectUuid()))
         .map(IssueDto::toDefaultIssue)
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
     }
 
     Map<String, Object> getProperties(String actionKey) {
@@ -344,7 +344,7 @@ public class BulkChangeAction implements IssuesWsAction {
     }
 
     List<Action> getActionsWithoutComment() {
-      return availableActions.stream().filter(action -> !action.key().equals(COMMENT_KEY)).collect(Collectors.toList());
+      return availableActions.stream().filter(action -> !action.key().equals(COMMENT_KEY)).collect(MoreCollectors.toList());
     }
 
     Optional<Action> getCommentAction() {
index 3809f366712664162bd6304e1d6c7fb016d33757..d3a392af1f57c403ca5a86ccc370a1494d2a1865 100644 (file)
@@ -32,7 +32,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.core.issue.FieldDiffs;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -87,7 +87,7 @@ public class ChangelogAction implements IssuesWsAction {
       ChangelogWsResponse wsResponse = Stream.of(request)
         .map(searchChangelog(dbSession))
         .map(buildResponse())
-        .collect(Collectors.toOneElement());
+        .collect(MoreCollectors.toOneElement());
       writeProtobuf(wsResponse, request, response);
     }
   }
@@ -100,7 +100,7 @@ public class ChangelogAction implements IssuesWsAction {
     return result -> Stream.of(ChangelogWsResponse.newBuilder())
       .peek(addChanges(result))
       .map(ChangelogWsResponse.Builder::build)
-      .collect(Collectors.toOneElement());
+      .collect(MoreCollectors.toOneElement());
   }
 
   private Consumer<ChangelogWsResponse.Builder> addChanges(ChangeLogResults results) {
@@ -153,16 +153,16 @@ public class ChangelogAction implements IssuesWsAction {
     ChangeLogResults(DbSession dbSession, String issueKey) {
       IssueDto dbIssue = issueFinder.getByKey(dbSession, issueKey);
       this.changes = dbClient.issueChangeDao().selectChangelogByIssue(dbSession, dbIssue.getKey());
-      List<String> logins = changes.stream().filter(change -> change.userLogin() != null).map(FieldDiffs::userLogin).collect(Collectors.toList());
-      this.users = dbClient.userDao().selectByLogins(dbSession, logins).stream().collect(Collectors.uniqueIndex(UserDto::getLogin));
-      this.files = dbClient.componentDao().selectByUuids(dbSession, getFileUuids(changes)).stream().collect(Collectors.uniqueIndex(ComponentDto::uuid, Function.identity()));
+      List<String> logins = changes.stream().filter(change -> change.userLogin() != null).map(FieldDiffs::userLogin).collect(MoreCollectors.toList());
+      this.users = dbClient.userDao().selectByLogins(dbSession, logins).stream().collect(MoreCollectors.uniqueIndex(UserDto::getLogin));
+      this.files = dbClient.componentDao().selectByUuids(dbSession, getFileUuids(changes)).stream().collect(MoreCollectors.uniqueIndex(ComponentDto::uuid, Function.identity()));
     }
 
     private Set<String> getFileUuids(List<FieldDiffs> changes) {
       return changes.stream()
         .filter(diffs -> diffs.diffs().containsKey(FILE))
         .flatMap(diffs -> Stream.of(diffs.get(FILE).newValue().toString(), diffs.get(FILE).oldValue().toString()))
-        .collect(Collectors.toSet());
+        .collect(MoreCollectors.toSet());
     }
 
     @CheckForNull
index f8a1720265e6b60faa90037f9cdecc119bffe9a1..613a097e0633b51a973af94fe9187e5c36fab91c 100644 (file)
@@ -27,7 +27,7 @@ import java.util.stream.Stream;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.issue.IssueChangeDto;
@@ -83,7 +83,7 @@ public class DeleteCommentAction implements IssuesWsAction {
       IssueDto issueDto = Stream.of(request)
         .map(loadCommentData(dbSession))
         .peek(deleteComment(dbSession))
-        .collect(Collectors.toOneElement())
+        .collect(MoreCollectors.toOneElement())
         .getIssueDto();
       responseWriter.write(issueDto.getKey(), request, response);
     }
index df1248790bbad07b8699571b89510c5929ac2325..d69c349c144c3ce88b27fa2c14b27b13349f3bb5 100644 (file)
@@ -28,7 +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.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.issue.IssueChangeDto;
@@ -94,7 +94,7 @@ public class EditCommentAction implements IssuesWsAction {
         .map(toWsRequest())
         .map(loadCommentData(dbSession))
         .peek(updateComment(dbSession))
-        .collect(Collectors.toOneElement())
+        .collect(MoreCollectors.toOneElement())
         .getIssueDto();
       responseWriter.write(issueDto.getKey(), request, response);
     }
index eb46fdecc6f6a943b7a49e3141258a1bbb3dc594..9e9a82711ddd467ac838ba7c14ee1850a5fac2be 100644 (file)
@@ -37,7 +37,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.Paging;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.es.Facets;
 import org.sonar.server.es.SearchOptions;
 import org.sonar.server.es.SearchResult;
@@ -308,7 +308,7 @@ public class SearchAction implements IssuesWsAction {
 
     // execute request
     SearchResult<IssueDoc> result = issueIndex.search(query, options);
-    List<String> issueKeys = result.getDocs().stream().map(IssueDoc::key).collect(Collectors.toList(result.getDocs().size()));
+    List<String> issueKeys = result.getDocs().stream().map(IssueDoc::key).collect(MoreCollectors.toList(result.getDocs().size()));
 
     // load the additional information to be returned in response
     SearchResponseLoader.Collector collector = new SearchResponseLoader.Collector(additionalFields, issueKeys);
index 69198d4bec25c612d553fe9aefd5a3e0068a5837..e0f16181d98528056bd9c41fa58e13ecf780a49e 100644 (file)
@@ -29,7 +29,7 @@ import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nullable;
 import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -135,7 +135,7 @@ public class SearchResponseLoader {
     }
     dbClient.organizationDao().selectByUuids(
       dbSession,
-      components.stream().map(ComponentDto::getOrganizationUuid).collect(Collectors.toSet()))
+      components.stream().map(ComponentDto::getOrganizationUuid).collect(MoreCollectors.toSet()))
       .forEach(result::addOrganization);
   }
 
index 7d8a676279988f1196b30752a9b781be97362d74..69cd1f677ee849e0bca8337d12a2326ab940193c 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.config.PropertyDefinitions;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.server.setting.ws.Setting;
@@ -47,7 +47,7 @@ import org.sonarqube.ws.Licenses.ListWsResponse;
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static org.sonar.api.CoreProperties.PERMANENT_SERVER_ID;
 import static org.sonar.api.PropertyType.LICENSE;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonarqube.ws.client.license.LicensesWsParameters.ACTION_LIST;
 
@@ -90,7 +90,7 @@ public class ListAction implements WsAction {
   private ListWsResponse doHandle(DbSession dbSession) {
     Map<String, PropertyDefinition> licenseDefinitionsByKeys = definitions.getAll().stream()
       .filter(definition -> LICENSE.equals(definition.type()))
-      .collect(Collectors.uniqueIndex(PropertyDefinition::key, Function.identity()));
+      .collect(MoreCollectors.uniqueIndex(PropertyDefinition::key, Function.identity()));
     Set<String> settingsKeys = new HashSet<>(licenseDefinitionsByKeys.keySet());
     settingsKeys.add(PERMANENT_SERVER_ID);
     List<Setting> settings = settingsFinder.loadGlobalSettings(dbSession, settingsKeys);
index 01f9ddbf741a66766530e48bb0bf4c0365bc3b3d..c1738c3dd08aaf22cda3a0a461f7f023e47f5583 100644 (file)
@@ -27,7 +27,7 @@ import java.util.List;
 import java.util.Map;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.es.BaseDoc;
 
 import static org.sonar.api.measures.Metric.Level.ERROR;
@@ -124,7 +124,7 @@ public class ProjectMeasuresDoc extends BaseDoc {
         .map(entry -> ImmutableMap.<String, Object>of(
           FIELD_MEASURES_KEY, entry.getKey(),
           FIELD_MEASURES_VALUE, entry.getValue()))
-        .collect(Collectors.toList()));
+        .collect(MoreCollectors.toList()));
     return this;
   }
 
index b62c5ddee27aff6400931b7376790f93ef2f6fd9..f50053693aef6348304873ae9242d5adbe8561ca 100644 (file)
@@ -41,7 +41,7 @@ import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
 import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder;
 import org.elasticsearch.search.sort.FieldSortBuilder;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.es.DefaultIndexSettingsElement;
 import org.sonar.server.es.EsClient;
 import org.sonar.server.es.SearchIdResult;
@@ -332,7 +332,7 @@ public class ProjectMeasuresIndex {
 
     return aggregation.getBuckets().stream()
       .map(Bucket::getKeyAsString)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   @FunctionalInterface
index ad0c597df08d6ec899e6d967bea33fa70577aa87..0aff113cd62d66c8190191d4756e7c564cc79b8f 100644 (file)
@@ -37,7 +37,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.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -230,7 +230,7 @@ public class ComponentAction implements MeasuresWsAction {
     List<MetricDtoWithBestValue> metricWithBestValueList = metrics.stream()
       .filter(MetricDtoFunctions.isOptimizedForBestValue())
       .map(new MetricDtoToMetricDtoWithBestValueFunction())
-      .collect(Collectors.toList(metrics.size()));
+      .collect(MoreCollectors.toList(metrics.size()));
     Map<Integer, MeasureDto> measuresByMetricId = Maps.uniqueIndex(measures, MeasureDto::getMetricId);
 
     for (MetricDtoWithBestValue metricWithBestValue : metricWithBestValueList) {
index 47bc1cc7657f5bc0067f8f83217bbc0e2d584fea..8b7bc9729b5d0b310ba7459b5a67d967209f25eb 100644 (file)
@@ -45,7 +45,7 @@ import javax.annotation.Nullable;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceTypes;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -137,7 +137,7 @@ public class ComponentTreeDataLoader {
     List<String> referenceComponentUUids = components.stream()
       .map(ComponentDto::getCopyResourceUuid)
       .filter(Objects::nonNull)
-      .collect(Collectors.toList(components.size()));
+      .collect(MoreCollectors.toList(components.size()));
     if (referenceComponentUUids.isEmpty()) {
       return emptyMap();
     }
@@ -207,7 +207,7 @@ public class ComponentTreeDataLoader {
     List<MetricDtoWithBestValue> metricDtosWithBestValueMeasure = metrics.stream()
       .filter(MetricDtoFunctions.isOptimizedForBestValue())
       .map(new MetricDtoToMetricDtoWithBestValue())
-      .collect(Collectors.toList(metrics.size()));
+      .collect(MoreCollectors.toList(metrics.size()));
     if (metricDtosWithBestValueMeasure.isEmpty()) {
       return;
     }
@@ -235,7 +235,7 @@ public class ComponentTreeDataLoader {
     return components
       .stream()
       .filter(new HasMeasure(measuresByComponentUuidAndMetric, metricToSort.get(), wsRequest))
-      .collect(Collectors.toList(components.size()));
+      .collect(MoreCollectors.toList(components.size()));
   }
 
   private static boolean componentWithMeasuresOnly(ComponentTreeWsRequest wsRequest) {
@@ -251,7 +251,7 @@ public class ComponentTreeDataLoader {
     return components.stream()
       .skip(offset(wsRequest.getPage(), wsRequest.getPageSize()))
       .limit(wsRequest.getPageSize())
-      .collect(Collectors.toList(wsRequest.getPageSize()));
+      .collect(MoreCollectors.toList(wsRequest.getPageSize()));
   }
 
   @CheckForNull
index 0c1df2aa426434f7692ac9c7d1202f900b22cf05..49caf8cf9e51283abe5e4304bd9ec86c5523965e 100644 (file)
@@ -30,7 +30,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.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -48,8 +48,8 @@ import static java.util.stream.Collectors.toMap;
 import static org.sonar.api.resources.Qualifiers.PROJECT;
 import static org.sonar.api.resources.Qualifiers.SUBVIEW;
 import static org.sonar.api.resources.Qualifiers.VIEW;
-import static org.sonar.core.util.stream.Collectors.toList;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.measure.ws.MeasureDtoToWsMeasure.dbToWsMeasure;
 import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter;
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
@@ -131,7 +131,7 @@ public class SearchAction implements MeasuresWsAction {
 
     private List<ComponentDto> searchProjects() {
       List<ComponentDto> componentDtos = searchByProjectKeys(dbSession, request.getProjectKeys());
-      checkArgument(ALLOWED_QUALIFIERS.containsAll(componentDtos.stream().map(ComponentDto::qualifier).collect(Collectors.toSet())),
+      checkArgument(ALLOWED_QUALIFIERS.containsAll(componentDtos.stream().map(ComponentDto::qualifier).collect(MoreCollectors.toSet())),
         "Only component of qualifiers %s are allowed", ALLOWED_QUALIFIERS);
       return getAuthorizedProjects(componentDtos);
     }
@@ -147,7 +147,7 @@ public class SearchAction implements MeasuresWsAction {
         // Meanwhile root is explicitly handled.
         return componentDtos;
       }
-      Set<String> projectUuids = componentDtos.stream().map(ComponentDto::projectUuid).collect(Collectors.toSet());
+      Set<String> projectUuids = componentDtos.stream().map(ComponentDto::projectUuid).collect(MoreCollectors.toSet());
       List<ComponentDto> projectDtos = dbClient.componentDao().selectByUuids(dbSession, projectUuids);
       Map<String, Long> projectIdsByUuids = projectDtos.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
       Set<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession,
@@ -155,7 +155,7 @@ public class SearchAction implements MeasuresWsAction {
         userSession.getUserId(), UserRole.USER);
       return componentDtos.stream()
         .filter(component -> authorizedProjectIds.contains(projectIdsByUuids.get(component.projectUuid())))
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
     }
 
     private List<MetricDto> searchMetrics() {
index 4f8e880ebb247d1a6e7af1ce835b80c556e20623..b916f287e68aa44b3a9e5f2c902c7019ecb749e2 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -121,7 +121,7 @@ public class SearchHistoryAction implements MeasuresWsAction {
       .map(SearchHistoryAction::toWsRequest)
       .map(search())
       .map(result -> new SearchHistoryResponseFactory(result).apply())
-      .collect(Collectors.toOneElement());
+      .collect(MoreCollectors.toOneElement());
 
     writeProtobuf(searchHistoryResponse, request, response);
   }
@@ -151,7 +151,7 @@ public class SearchHistoryAction implements MeasuresWsAction {
     Date to = parseEndingDateOrDateTime(request.getTo());
     PastMeasureQuery dbQuery = new PastMeasureQuery(
       result.getComponent().uuid(),
-      result.getMetrics().stream().map(MetricDto::getId).collect(Collectors.toList()),
+      result.getMetrics().stream().map(MetricDto::getId).collect(MoreCollectors.toList()),
       from == null ? null : from.getTime(),
       to == null ? null : (to.getTime() + 1_000L));
     return dbClient.measureDao().selectPastMeasures(dbSession, dbQuery);
@@ -171,8 +171,8 @@ public class SearchHistoryAction implements MeasuresWsAction {
   private List<MetricDto> searchMetrics(DbSession dbSession, SearchHistoryRequest request) {
     List<MetricDto> metrics = dbClient.metricDao().selectByKeys(dbSession, request.getMetrics());
     if (request.getMetrics().size() > metrics.size()) {
-      Set<String> requestedMetrics = request.getMetrics().stream().collect(Collectors.toSet());
-      Set<String> foundMetrics = metrics.stream().map(MetricDto::getKey).collect(Collectors.toSet());
+      Set<String> requestedMetrics = request.getMetrics().stream().collect(MoreCollectors.toSet());
+      Set<String> foundMetrics = metrics.stream().map(MetricDto::getKey).collect(MoreCollectors.toSet());
 
       Set<String> unfoundMetrics = Sets.difference(requestedMetrics, foundMetrics).immutableCopy();
       throw new IllegalArgumentException(format("Metrics %s are not found", String.join(", ", unfoundMetrics)));
index db7a6ee94a94a24c58171aaa1243aecfbfe0c0db..3169971a3627fedf37f3478d02b1ab536a24e971 100644 (file)
@@ -25,7 +25,7 @@ import java.util.Map;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
 import java.util.stream.Stream;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.MeasureDto;
 import org.sonar.db.metric.MetricDto;
@@ -53,7 +53,7 @@ class SearchHistoryResponseFactory {
       .map(addPaging())
       .map(addMeasures())
       .map(SearchHistoryResponse.Builder::build)
-      .collect(Collectors.toOneElement());
+      .collect(MoreCollectors.toOneElement());
   }
 
   private UnaryOperator<SearchHistoryResponse.Builder> addPaging() {
@@ -61,8 +61,8 @@ class SearchHistoryResponseFactory {
   }
 
   private UnaryOperator<SearchHistoryResponse.Builder> addMeasures() {
-    Map<Integer, MetricDto> metricsById = result.getMetrics().stream().collect(Collectors.uniqueIndex(MetricDto::getId));
-    Map<String, SnapshotDto> analysesByUuid = result.getAnalyses().stream().collect(Collectors.uniqueIndex(SnapshotDto::getUuid));
+    Map<Integer, MetricDto> metricsById = result.getMetrics().stream().collect(MoreCollectors.uniqueIndex(MetricDto::getId));
+    Map<String, SnapshotDto> analysesByUuid = result.getAnalyses().stream().collect(MoreCollectors.uniqueIndex(SnapshotDto::getUuid));
     Table<MetricDto, SnapshotDto, MeasureDto> measuresByMetricByAnalysis = HashBasedTable.create(result.getMetrics().size(), result.getAnalyses().size());
     result.getMeasures().forEach(m -> measuresByMetricByAnalysis.put(metricsById.get(m.getMetricId()), analysesByUuid.get(m.getAnalysisUuid()), m));
 
index ef16d831b3d2d60e08c13442399442fb7298b4a5..22d7440bbd0998b65c23d1955ca59f92f35e69a4 100644 (file)
@@ -25,7 +25,7 @@ import com.google.common.collect.Table;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.MeasureDto;
@@ -67,7 +67,7 @@ class SearchHistoryResult {
 
   SearchHistoryResult setAnalyses(List<SnapshotDto> analyses) {
     this.paging = Common.Paging.newBuilder().setPageIndex(request.getPage()).setPageSize(request.getPageSize()).setTotal(analyses.size()).build();
-    this.analyses = analyses.stream().skip(offset(request.getPage(), request.getPageSize())).limit(request.getPageSize()).collect(Collectors.toList());
+    this.analyses = analyses.stream().skip(offset(request.getPage(), request.getPageSize())).limit(request.getPageSize()).collect(MoreCollectors.toList());
 
     return this;
   }
@@ -86,11 +86,11 @@ class SearchHistoryResult {
   }
 
   SearchHistoryResult setMeasures(List<MeasureDto> measures) {
-    Set<String> analysisUuids = analyses.stream().map(SnapshotDto::getUuid).collect(Collectors.toHashSet());
+    Set<String> analysisUuids = analyses.stream().map(SnapshotDto::getUuid).collect(MoreCollectors.toHashSet());
     ImmutableList.Builder<MeasureDto> measuresBuilder = ImmutableList.builder();
     List<MeasureDto> filteredMeasures = measures.stream()
       .filter(measure -> analysisUuids.contains(measure.getAnalysisUuid()))
-      .collect(Collectors.toArrayList());
+      .collect(MoreCollectors.toArrayList());
     measuresBuilder.addAll(filteredMeasures);
     measuresBuilder.addAll(computeBestValues(filteredMeasures));
 
index 377c54a37e74afce3f63403d602a9394fcc0b2c5..3df6ce3c812bc15e2b82bc3a78500631fa8a598f 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.notification;
 import java.util.List;
 import java.util.function.Predicate;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -64,7 +64,7 @@ public class NotificationUpdater {
         .build(),
       dbSession).stream()
       .filter(notificationScope(project))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     checkArgument(existingNotification.isEmpty()
       || !PROP_NOTIFICATION_VALUE.equals(existingNotification.get(0).getValue()), "Notification already added");
 
@@ -95,7 +95,7 @@ public class NotificationUpdater {
         .build(),
       dbSession).stream()
       .filter(notificationScope(project))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     checkArgument(!existingNotification.isEmpty() && PROP_NOTIFICATION_VALUE.equals(existingNotification.get(0).getValue()), "Notification doesn't exist");
 
     dbClient.propertiesDao().delete(dbSession, new PropertyDto()
index a542627c587d62caedaa2bcf21ad8be6b268351f..921387991bdecda7e2507742bbced638ce5c16a4 100644 (file)
@@ -44,7 +44,7 @@ import org.sonarqube.ws.client.notification.AddRequest;
 
 import static java.util.Optional.empty;
 import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
 import static org.sonar.server.ws.WsUtils.checkRequest;
index 380718b1dcd68d0e9c92cd0bc2f93f1d73c40748..d7d0a8bbd458d1bf2be4a37bbd5ea3960f92a0b8 100644 (file)
@@ -36,7 +36,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.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -53,7 +53,7 @@ import static java.util.Comparator.comparing;
 import static java.util.Comparator.naturalOrder;
 import static java.util.Comparator.nullsFirst;
 import static org.sonar.core.util.Protobuf.setNullable;
-import static org.sonar.core.util.stream.Collectors.toOneElement;
+import static org.sonar.core.util.stream.MoreCollectors.toOneElement;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION;
 import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
@@ -71,9 +71,9 @@ public class ListAction implements NotificationsWsAction {
   public ListAction(NotificationCenter notificationCenter, DbClient dbClient, UserSession userSession) {
     this.dbClient = dbClient;
     this.userSession = userSession;
-    this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true").stream().sorted().collect(Collectors.toList());
-    this.perProjectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true").stream().sorted().collect(Collectors.toList());
-    this.channels = notificationCenter.getChannels().stream().map(NotificationChannel::getKey).sorted().collect(Collectors.toList());
+    this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true").stream().sorted().collect(MoreCollectors.toList());
+    this.perProjectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true").stream().sorted().collect(MoreCollectors.toList());
+    this.channels = notificationCenter.getChannels().stream().map(NotificationChannel::getKey).sorted().collect(MoreCollectors.toList());
   }
 
   @Override
@@ -154,20 +154,20 @@ public class ListAction implements NotificationsWsAction {
     Set<Long> componentIds = properties.stream()
       .map(PropertyDto::getResourceId)
       .filter(Objects::nonNull)
-      .collect(Collectors.toSet(properties.size()));
+      .collect(MoreCollectors.toSet(properties.size()));
     return dbClient.componentDao().selectByIds(dbSession, componentIds)
       .stream()
       .filter(c -> authorizedComponentUuids.contains(c.uuid()))
-      .collect(Collectors.uniqueIndex(ComponentDto::getId));
+      .collect(MoreCollectors.uniqueIndex(ComponentDto::getId));
   }
 
   private Map<String, OrganizationDto> getOrganizations(DbSession dbSession, Collection<ComponentDto> values) {
     Set<String> organizationUuids = values.stream()
       .map(ComponentDto::getOrganizationUuid)
-      .collect(Collectors.toSet());
+      .collect(MoreCollectors.toSet());
     return dbClient.organizationDao().selectByUuids(dbSession, organizationUuids)
       .stream()
-      .collect(Collectors.uniqueIndex(OrganizationDto::getUuid));
+      .collect(MoreCollectors.uniqueIndex(OrganizationDto::getUuid));
   }
 
   private static Function<PropertyDto, Notification> toWsNotification(Notification.Builder notification,
index 6837001fa34b6e33c0ca19901b15f1c35f0b5f3a..46d45212ae3a40a60e7456ad935f57e18a28716a 100644 (file)
@@ -23,7 +23,7 @@ import java.util.List;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -137,7 +137,7 @@ public class DeleteAction implements OrganizationsWsAction {
     List<QualityProfileDto> profiles = dbClient.qualityProfileDao().selectAll(dbSession, organization);
     List<String> profileKeys = profiles.stream()
       .map(QualityProfileDto::getKey)
-      .collect(Collectors.toArrayList(profiles.size()));
+      .collect(MoreCollectors.toArrayList(profiles.size()));
     qProfileFactory.deleteByKeys(dbSession, profileKeys);
     dbSession.commit();
   }
index 1dffd2a3e119c698a3c7582f068fccb086521256..88ff3780daa7f1022f86d8dfde00de51ddc2e2a4 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.server.ws.WebService.SelectionMode;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -103,11 +103,11 @@ public class SearchMembersAction implements OrganizationsWsAction {
       SearchOptions searchOptions = buildSearchOptions(request);
 
       SearchResult<UserDoc> searchResults = userIndex.search(userQuery.build(), searchOptions);
-      List<String> orderedLogins = searchResults.getDocs().stream().map(UserDoc::login).collect(Collectors.toList());
+      List<String> orderedLogins = searchResults.getDocs().stream().map(UserDoc::login).collect(MoreCollectors.toList());
 
       List<UserDto> users = dbClient.userDao().selectByLogins(dbSession, orderedLogins).stream()
         .sorted(Ordering.explicit(orderedLogins).onResultOf(UserDto::getLogin))
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
 
       Multiset<String> groupCountByLogin = null;
       if (userSession.hasPermission(OrganizationPermission.ADMINISTER, organization)) {
index 9a9f2b1d2cfcda68910c28628be1945fb946b804..858338adc780772d4b628b474ccacee217850bb8 100644 (file)
@@ -31,7 +31,7 @@ import org.apache.commons.lang.StringUtils;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.server.ServerSide;
 import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -103,7 +103,7 @@ public class PermissionTemplateService {
       copyPermissions(dbSession, template, project, null);
     }
     dbSession.commit();
-    indexProjectPermissions(dbSession, projects.stream().map(ComponentDto::uuid).collect(Collectors.toList()));
+    indexProjectPermissions(dbSession, projects.stream().map(ComponentDto::uuid).collect(MoreCollectors.toList()));
   }
 
   /**
index 9e44dfff342287ab160ed8499565aeba5823819c..9ee21a3ef2b5fb6ab321492fcc9396333b031478 100644 (file)
@@ -29,7 +29,7 @@ import java.util.Set;
 import java.util.stream.Stream;
 import org.elasticsearch.action.index.IndexRequest;
 import org.sonar.api.utils.DateUtils;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.server.es.BulkIndexer;
@@ -41,7 +41,7 @@ import org.sonar.server.es.StartupIndexer;
 import org.sonar.server.permission.index.PermissionIndexerDao.Dto;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.core.util.stream.Collectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 
 /**
  * Manages the synchronization of indexes with authorization settings defined in database:
@@ -62,7 +62,7 @@ public class PermissionIndexer implements ProjectIndexer, StartupIndexer {
   public PermissionIndexer(DbClient dbClient, EsClient esClient, NeedAuthorizationIndexer... needAuthorizationIndexers) {
     this(dbClient, esClient, Arrays.stream(needAuthorizationIndexers)
       .map(NeedAuthorizationIndexer::getAuthorizationScope)
-      .collect(Collectors.toList(needAuthorizationIndexers.length)));
+      .collect(MoreCollectors.toList(needAuthorizationIndexers.length)));
   }
 
   @VisibleForTesting
index e1d0db778db6873c3caa511f0e03281e2bc2fd61..1f6e95b0f23f8afaf47162ee7122fdb6ea1f45ab 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.Paging;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -162,7 +162,7 @@ public class GroupsAction implements PermissionsWsAction {
     if (groups.isEmpty()) {
       return emptyList();
     }
-    List<Integer> ids = groups.stream().map(GroupDto::getId).collect(Collectors.toList(groups.size()));
+    List<Integer> ids = groups.stream().map(GroupDto::getId).collect(MoreCollectors.toList(groups.size()));
     return dbClient.groupPermissionDao().selectByGroupIds(dbSession, org.getUuid(), ids, project.isPresent() ? project.get().getId() : null);
   }
 }
index 219f3f6f88ee573eec277f08258e0b919aa00cc1..7a864c6471f06ba6d061c1cbf1cacf1426b13af5 100644 (file)
@@ -32,7 +32,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.server.authentication.IdentityProvider;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.process.ProcessProperties;
 import org.sonar.server.authentication.IdentityProviderRepository;
 import org.sonar.server.platform.ServerId;
@@ -90,7 +90,7 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit
       .stream()
       .filter(IdentityProvider::isEnabled)
       .map(IdentityProvider::getName)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   private List<String> getAllowsToSignUpEnabledIdentityProviders() {
@@ -99,7 +99,7 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit
       .filter(IdentityProvider::isEnabled)
       .filter(IdentityProvider::allowsUsersToSignUp)
       .map(IdentityProvider::getName)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   private boolean getForceAuthentication() {
index 12220c383cd36b5eb8e24cda6b6875f37be3e7a4..c6d77b4da57bc10c0a66d7d22b14b313538f8f86 100644 (file)
@@ -32,7 +32,7 @@ import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static java.lang.String.format;
 
@@ -54,7 +54,7 @@ public class RedirectFilter implements Filter {
     Predicate<Redirect> match = redirect -> redirect.test(path);
     List<Redirect> redirects = REDIRECTS.stream()
       .filter(match)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
 
     switch (redirects.size()) {
       case 0:
index 2be3a516bc497e900128c3a413138af6addf0eca..ade4e46d3e2d319ec595cad98e12cf739c1309b4 100644 (file)
@@ -25,7 +25,7 @@ import org.apache.commons.io.FileUtils;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.process.ProcessId;
 import org.sonar.server.platform.ServerLogging;
 import org.sonar.server.user.UserSession;
@@ -58,7 +58,7 @@ public class LogsAction implements SystemWsAction {
       .setPossibleValues(stream(ProcessId.values())
         .map(ProcessId::getKey)
         .sorted()
-        .collect(Collectors.toList(ProcessId.values().length)))
+        .collect(MoreCollectors.toList(ProcessId.values().length)))
       .setDefaultValue(ProcessId.APP.getKey())
       .setSince("6.2")
       .setDescription("Process to get logs from");
index 9a2f3a6fc765ff3e1465169e3e071c7d381fe9fe..2a119d7a7ed6de4730dfe6c434a635ba9b59cb67 100644 (file)
@@ -31,7 +31,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.utils.text.JsonWriter;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -39,7 +39,7 @@ import org.sonar.server.user.UserSession;
 
 import static java.util.Optional.ofNullable;
 import static org.sonar.api.web.UserRole.USER;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 import static org.sonarqube.ws.client.project.ProjectsWsParameters.ACTION_INDEX;
 
@@ -139,13 +139,13 @@ public class IndexAction implements ProjectsWsAction {
       // Meanwhile root is explicitly handled.
       return components;
     }
-    Set<String> projectUuids = components.stream().map(ComponentDto::projectUuid).collect(Collectors.toSet());
+    Set<String> projectUuids = components.stream().map(ComponentDto::projectUuid).collect(MoreCollectors.toSet());
     List<ComponentDto> projects = dbClient.componentDao().selectByUuids(dbSession, projectUuids);
     Map<String, Long> projectIdsByUuids = projects.stream().collect(uniqueIndex(ComponentDto::uuid, ComponentDto::getId));
     Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession, projectIdsByUuids.values(), userSession.getUserId(), USER);
     return components.stream()
       .filter(component -> authorizedProjectIds.contains(projectIdsByUuids.get(component.projectUuid())))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   private static void addProject(JsonWriter json, ComponentDto project) {
index ea9b7ec553781a24b330a80693a9d417f3339b43..5505546966d086fa7a2ac8ed77c5b3fea7ab9701 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -45,7 +45,7 @@ import org.sonarqube.ws.client.projectanalysis.EventCategory;
 import org.sonarqube.ws.client.projectanalysis.SearchRequest;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.core.util.stream.Collectors.toOneElement;
+import static org.sonar.core.util.stream.MoreCollectors.toOneElement;
 import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
 import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
@@ -133,7 +133,7 @@ public class SearchAction implements ProjectAnalysesWsAction {
 
   private Consumer<SearchResults.Builder> addEvents() {
     return data -> {
-      List<String> analyses = data.getAnalyses().stream().map(SnapshotDto::getUuid).collect(Collectors.toList());
+      List<String> analyses = data.getAnalyses().stream().map(SnapshotDto::getUuid).collect(MoreCollectors.toList());
       data.setEvents(dbClient.eventDao().selectByAnalysisUuids(data.getDbSession(), analyses));
     };
   }
index fe168228ee31c7faf92cc2670ac815d41cc455a5..07152e97f199f15d74781a15039e40a19da4d066 100644 (file)
@@ -22,7 +22,7 @@ package org.sonar.server.projectanalysis.ws;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Stream;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.event.EventDto;
 import org.sonarqube.ws.ProjectAnalyses.Analysis;
@@ -47,7 +47,7 @@ class SearchResponseBuilder {
       .peek(addAnalyses(searchResults))
       .peek(addPagination(searchResults))
       .map(SearchResponse.Builder::build)
-      .collect(Collectors.toOneElement());
+      .collect(MoreCollectors.toOneElement());
   }
 
   private Consumer<SearchResponse.Builder> addAnalyses(SearchResults searchResults) {
index 039ec2ca5c4114e5474cb9c2f5a6b75c99aaa7ef..8e725ccc6ae0bbaf9eefe10c50e81ec867a97c43 100644 (file)
@@ -24,7 +24,7 @@ import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 import org.sonar.api.utils.Paging;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.SnapshotDto;
@@ -48,7 +48,7 @@ class SearchResults {
   }
 
   private ListMultimap<String, EventDto> buildEvents(List<EventDto> events) {
-    return events.stream().collect(Collectors.index(EventDto::getAnalysisUuid));
+    return events.stream().collect(MoreCollectors.index(EventDto::getAnalysisUuid));
   }
 
   static Builder builder(DbSession dbSession, SearchRequest request) {
@@ -82,7 +82,7 @@ class SearchResults {
           .limit(request.getPageSize());
       }
 
-      this.analyses = stream.collect(Collectors.toList());
+      this.analyses = stream.collect(MoreCollectors.toList());
       this.countAnalyses = analyses.size();
       return this;
     }
@@ -110,14 +110,14 @@ class SearchResults {
 
     private void filterByCategory() {
       ListMultimap<String, String> eventCategoriesByAnalysisUuid = events.stream()
-        .collect(Collectors.index(EventDto::getAnalysisUuid, EventDto::getCategory));
+        .collect(MoreCollectors.index(EventDto::getAnalysisUuid, EventDto::getCategory));
       Predicate<SnapshotDto> byCategory = a -> eventCategoriesByAnalysisUuid.get(a.getUuid()).contains(request.getCategory().getLabel());
       this.countAnalyses = (int) analyses.stream().filter(byCategory).count();
       this.analyses = analyses.stream()
         .filter(byCategory)
         .skip(Paging.offset(request.getPage(), request.getPageSize()))
         .limit(request.getPageSize())
-        .collect(Collectors.toList());
+        .collect(MoreCollectors.toList());
     }
 
     SearchResults build() {
index 039ee751d1498bdbb83d7317f2a5015f5e2e6639..8fdffb9b20b925a2670b5e7242e7763987d80637 100644 (file)
@@ -27,7 +27,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.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -89,7 +89,7 @@ public class SetAction implements ProjectTagsWsAction {
       .map(t -> t.toLowerCase(Locale.ENGLISH))
       .map(SetAction::checkTag)
       .distinct()
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
 
     try (DbSession dbSession = dbClient.openSession(false)) {
       ComponentDto project = componentFinder.getByKey(dbSession, projectKey);
index fa5decc0225c26185fbcf5f978740c12d5ca699e..4d9e79bd748247c2100f0a64d2914e04274048a8 100644 (file)
@@ -24,7 +24,7 @@ import java.util.List;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.Paging;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualitygate.ProjectQgateAssociation;
@@ -70,11 +70,11 @@ public class QgateProjectFinder {
   }
 
   private static List<ProjectQgateAssociationDto> getPaginatedProjects(List<ProjectQgateAssociationDto> projects, Paging paging) {
-    return projects.stream().skip(paging.offset()).limit(paging.pageSize()).collect(Collectors.toList());
+    return projects.stream().skip(paging.offset()).limit(paging.pageSize()).collect(MoreCollectors.toList());
   }
 
   private static List<ProjectQgateAssociation> toProjectAssociations(List<ProjectQgateAssociationDto> dtos) {
-    return dtos.stream().map(ProjectQgateAssociationDto::toQgateAssociation).collect(Collectors.toList());
+    return dtos.stream().map(ProjectQgateAssociationDto::toQgateAssociation).collect(MoreCollectors.toList());
   }
 
   private List<ProjectQgateAssociationDto> keepAuthorizedProjects(DbSession dbSession, List<ProjectQgateAssociationDto> projects) {
@@ -84,9 +84,9 @@ public class QgateProjectFinder {
       // Meanwhile root is explicitly handled.
       return projects;
     }
-    List<Long> projectIds = projects.stream().map(ProjectQgateAssociationDto::getId).collect(Collectors.toList());
+    List<Long> projectIds = projects.stream().map(ProjectQgateAssociationDto::getId).collect(MoreCollectors.toList());
     Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession, projectIds, userSession.getUserId(), UserRole.USER);
-    return projects.stream().filter(project -> authorizedProjectIds.contains(project.getId())).collect(Collectors.toList());
+    return projects.stream().filter(project -> authorizedProjectIds.contains(project.getId())).collect(MoreCollectors.toList());
   }
 
   public static class Association {
index feab37f24b585c946f50c4da4fb9ad53b275bb1b..13d31d912d23d5b492fa0d1c066939c763861854 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Set;
 import org.sonar.api.measures.CoreMetrics;
 
 import static org.sonar.api.measures.Metric.ValueType.RATING;
-import static org.sonar.core.util.stream.Collectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 
 public class ValidRatingMetrics {
 
index 5bd0730b6e66e8a7368fc91ec19c14f75bbbcf64..befd97398bbb339b7f2bb6aa36e84f6f871497f3 100644 (file)
@@ -27,7 +27,7 @@ import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import org.picocontainer.Startable;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.ActiveRuleDto;
@@ -78,6 +78,6 @@ public class CachingRuleActivatorContextFactory extends RuleActivatorContextFact
 
   private Map<RuleKey, ActiveRuleDto> loadActiveRulesOfQualityProfile(DbSession session, String profileKey) {
     return dbClient.activeRuleDao().selectByProfileKey(session, profileKey).stream()
-      .collect(Collectors.uniqueIndex(dto -> dto.getKey().ruleKey()));
+      .collect(MoreCollectors.uniqueIndex(dto -> dto.getKey().ruleKey()));
   }
 }
index e89d2fd1e0d9c9c98a4822714becf90b93120b1a..34a354f2502501cc912b7dfbcbac37b9495f98bc 100644 (file)
@@ -40,7 +40,7 @@ import org.sonar.api.utils.ValidationMessages;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
@@ -123,12 +123,12 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository
     Map<String, List<DefinedQProfile.Builder>> buildersByLanguage = Multimaps.asMap(rulesProfilesByLanguage)
       .entrySet()
       .stream()
-      .collect(Collectors.uniqueIndex(Map.Entry::getKey, DefinedQProfileRepositoryImpl::toQualityProfileBuilders));
+      .collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, DefinedQProfileRepositoryImpl::toQualityProfileBuilders));
     return buildersByLanguage
       .entrySet()
       .stream()
       .filter(DefinedQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault)
-      .collect(Collectors.uniqueIndex(Map.Entry::getKey, entry -> toQualityProfiles(entry.getValue()), buildersByLanguage.size()));
+      .collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, entry -> toQualityProfiles(entry.getValue()), buildersByLanguage.size()));
   }
 
   /**
@@ -162,7 +162,7 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository
     Set<String> declaredDefaultProfileNames = entry.getValue().stream()
       .filter(DefinedQProfile.Builder::isDeclaredDefault)
       .map(DefinedQProfile.Builder::getName)
-      .collect(Collectors.toSet());
+      .collect(MoreCollectors.toSet());
     checkState(declaredDefaultProfileNames.size() <= 1, "Several Quality profiles are flagged as default for the language %s: %s", entry.getKey(), declaredDefaultProfileNames);
     return true;
   }
@@ -195,6 +195,6 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository
     MessageDigest md5Digest = DigestUtils.getMd5Digest();
     return builders.stream()
       .map(builder -> builder.build(md5Digest))
-      .collect(Collectors.toList(builders.size()));
+      .collect(MoreCollectors.toList(builders.size()));
   }
 }
index 8a65e4671d27e3ee31a7f7f328bd3be3780f7aec..b01609fc17bcaa8163c3bfa86d2aab82ccfd7191 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.util.UtcDateUtils;
 
 import static java.util.function.Function.identity;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 
 /**
  * Represents the array of JSON objects stored in the value of the
index 6c07ddbe83e4f51d64bebfdd3bf35ee806a0c6e5..7b54ecb583393ddac4e7fec6a0b7b9af52e03cc3 100644 (file)
@@ -26,7 +26,7 @@ import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.ActiveRuleKey;
@@ -88,7 +88,7 @@ public class ActiveRuleIndexer extends BaseIndexer {
     deleteKeys(changes.stream()
       .filter(c -> c.getType().equals(ActiveRuleChange.Type.DEACTIVATED))
       .map(ActiveRuleChange::getKey)
-      .collect(Collectors.toList(changes.size())));
+      .collect(MoreCollectors.toList(changes.size())));
 
     index();
   }
index 301e803db668af73c6289f53574932f3ba023408..2a0cf91dfb627718385f8b0b4a9edf630a440616 100644 (file)
@@ -29,7 +29,7 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.QProfileChangeDto;
@@ -55,7 +55,7 @@ public class ChangelogLoader {
     List<QProfileChangeDto> dtos = dbClient.qProfileChangeDao().selectByQuery(dbSession, query);
     List<Change> changes = dtos.stream()
       .map(Change::from)
-      .collect(Collectors.toList(dtos.size()));
+      .collect(MoreCollectors.toList(dtos.size()));
     completeUserAndRuleNames(dbSession, changes);
 
     int total = dbClient.qProfileChangeDao().countForProfileKey(dbSession, query.getProfileKey());
@@ -63,13 +63,13 @@ public class ChangelogLoader {
   }
 
   private void completeUserAndRuleNames(DbSession dbSession, List<Change> changes) {
-    Set<String> logins = changes.stream().filter(c -> c.userLogin != null).map(c -> c.userLogin).collect(Collectors.toSet());
+    Set<String> logins = changes.stream().filter(c -> c.userLogin != null).map(c -> c.userLogin).collect(MoreCollectors.toSet());
     Map<String, String> userNamesByLogins = dbClient.userDao()
       .selectByLogins(dbSession, logins)
       .stream()
       .collect(java.util.stream.Collectors.toMap(UserDto::getLogin, UserDto::getName));
 
-    Set<RuleKey> ruleKeys = changes.stream().filter(c -> c.ruleKey != null).map(c -> c.ruleKey).collect(Collectors.toSet());
+    Set<RuleKey> ruleKeys = changes.stream().filter(c -> c.ruleKey != null).map(c -> c.ruleKey).collect(MoreCollectors.toSet());
     Map<RuleKey, String> ruleNamesByKeys = dbClient.ruleDao()
       .selectDefinitionByKeys(dbSession, Lists.newArrayList(ruleKeys))
       .stream()
index bd1e52f502b973c26425e049a438295649a82360..63fdcda63c95e18d396ed87e74870edc77a1a689 100644 (file)
@@ -26,7 +26,7 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.QualityProfileDto;
@@ -100,6 +100,6 @@ public class DeleteAction implements QProfileWsAction {
   private static List<String> toKeys(QualityProfileDto profile, List<QualityProfileDto> descendants) {
     return Stream.concat(Stream.of(profile), descendants.stream())
       .map(QualityProfileDto::getKee)
-      .collect(Collectors.toList(descendants.size() + 1));
+      .collect(MoreCollectors.toList(descendants.size() + 1));
   }
 }
index cb6435d1a8fb7fad308659323a55645a2dba692f..0867d67248a4987f69db4baf3d3d75ae92217c72 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.Response.Stream;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -90,7 +90,7 @@ public class ExportAction implements QProfileWsAction {
       .map(language -> exporters.exportersForLanguage(language.getKey()))
       .flatMap(Collection::stream)
       .map(ProfileExporter::getKey)
-      .collect(Collectors.toSet());
+      .collect(MoreCollectors.toSet());
     if (!exporterKeys.isEmpty()) {
       action.createParam(PARAM_FORMAT)
         .setDescription("Output format. If left empty, the same format as api/qualityprofiles/backup is used. " +
index 028f3caefabb964704e44c9c1c2d1b7dd9d33ad2..f13794632bcd590d8f9ee25acc85b136b6f5ded4 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.api.resources.Languages;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.core.util.Uuids;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
@@ -183,6 +183,6 @@ public class QProfileReference {
       .setExampleValue("Sonar way");
     action.createParam(PARAM_LANGUAGE)
       .setDescription("A quality profile language. If this parameter is set, profileKey must not be set and profileName must be set to disambiguate.")
-      .setPossibleValues(Arrays.stream(languages.all()).map(Language::getKey).collect(Collectors.toSet()));
+      .setPossibleValues(Arrays.stream(languages.all()).map(Language::getKey).collect(MoreCollectors.toSet()));
   }
 }
index 272152e92b5b3ca4c90babe924d59bee44d26193..c7ce5e98da0e918717f08d2f391e3663dbe9ff14 100644 (file)
@@ -42,7 +42,7 @@ import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -113,7 +113,7 @@ public class RegisterRules implements Startable {
       session.commit();
 
       persistRepositories(session, context.repositories());
-      ruleIndexer.delete(removedRules.stream().map(RuleDefinitionDto::getKey).collect(Collectors.toList(removedRules.size())));
+      ruleIndexer.delete(removedRules.stream().map(RuleDefinitionDto::getKey).collect(MoreCollectors.toList(removedRules.size())));
       ruleIndexer.index(getDefaultOrganization(), keysToIndex);
       activeRuleIndexer.index(changes);
       profiler.stopDebug();
@@ -132,7 +132,7 @@ public class RegisterRules implements Startable {
     List<RuleRepositoryDto> dtos = repositories
       .stream()
       .map(r -> new RuleRepositoryDto(r.key(), r.language(), r.name()))
-      .collect(Collectors.toList(repositories.size()));
+      .collect(MoreCollectors.toList(repositories.size()));
     dbClient.ruleRepositoryDao().insert(dbSession, dtos);
     dbSession.commit();
   }
index 77f329e5f8fb5144f261ce57f646eb4d478d9124..8161c9b2c997ed0f5193cc7303ed38e505a204c4 100644 (file)
@@ -36,7 +36,7 @@ import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.qualityprofile.ActiveRuleDto;
@@ -86,7 +86,7 @@ public class ActiveRuleCompleter {
     if (profileKey != null) {
       // Load details of active rules on the selected profile
       List<ActiveRuleDto> activeRuleDtos = dbClient.activeRuleDao().selectByProfileKey(dbSession, profileKey);
-      Map<RuleKey, ActiveRuleDto> activeRuleByRuleKey = activeRuleDtos.stream().collect(Collectors.uniqueIndex(d -> d.getKey().ruleKey()));
+      Map<RuleKey, ActiveRuleDto> activeRuleByRuleKey = activeRuleDtos.stream().collect(MoreCollectors.uniqueIndex(d -> d.getKey().ruleKey()));
       ListMultimap<ActiveRuleKey, ActiveRuleParamDto> activeRuleParamsByActiveRuleKey = activeRuleDtosToActiveRuleParamDtos(dbSession, activeRuleDtos);
 
       for (RuleDto rule : rules) {
index b9cf2a6087d65854835cde1f7bb659cbb256a6af..1d3f0c7f3191fbbe2694c223b1491593b230aaf6 100644 (file)
@@ -29,7 +29,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.rule.RuleRepositoryDto;
@@ -88,7 +88,7 @@ public class RepositoriesAction implements RulesWsAction {
 
     return selectFromDb(languageKey).stream()
       .filter(r -> pattern.matcher(r.getKey()).matches() || pattern.matcher(r.getName()).matches())
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   private Collection<RuleRepositoryDto> selectFromDb(@Nullable String language) {
index 95be46d533c20f98073a082df3c12427603a12c0..a1614ff80de4737dd74ff11d652c3608168e2df8 100644 (file)
@@ -43,7 +43,7 @@ import org.sonar.api.rules.RuleType;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.rule.RuleDefinitionDto;
@@ -348,11 +348,11 @@ public class SearchAction implements RulesWsAction {
         rules.add(rule);
       }
     }
-    List<Integer> ruleIds = rules.stream().map(RuleDto::getId).collect(Collectors.toList());
+    List<Integer> ruleIds = rules.stream().map(RuleDto::getId).collect(MoreCollectors.toList());
     List<Integer> templateRuleIds = rules.stream()
       .map(RuleDto::getTemplateId)
       .filter(Objects::nonNull)
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     List<RuleDefinitionDto> templateRules = dbClient.ruleDao().selectDefinitionByIds(dbSession, templateRuleIds);
     List<RuleParamDto> ruleParamDtos = dbClient.ruleDao().selectRuleParamsByRuleIds(dbSession, ruleIds);
     return new SearchResult()
index 97297d7ff7d890efe665e16c29f70e64e5931ad3..cafa7da131ac110d2eec61ac0fe1d128213ff284 100644 (file)
@@ -30,7 +30,7 @@ import javax.annotation.Nullable;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.property.PropertyDto;
@@ -74,7 +74,7 @@ public class ShowAction implements ServerIdWsAction {
     userSession.checkIsSystemAdministrator();
     try (DbSession dbSession = dbClient.openSession(true)) {
       Map<String, PropertyDto> properties = dbClient.propertiesDao().selectGlobalPropertiesByKeys(dbSession, SETTINGS_KEYS).stream()
-        .collect(Collectors.uniqueIndex(PropertyDto::getKey, Function.identity()));
+        .collect(MoreCollectors.uniqueIndex(PropertyDto::getKey, Function.identity()));
       writeProtobuf(doHandle(properties), request, response);
     }
   }
index 060eccd83335a8156d63ab396ac335d00b41d526..726c856c1f1e8d5756b73be2104be95b68f92122 100644 (file)
@@ -29,7 +29,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.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -115,7 +115,7 @@ public class ResetAction implements SettingsWsAction {
         PropertyDefinition definition = definitions.get(key);
         return definition != null ? definition.key() : key;
       })
-      .collect(Collectors.toSet()));
+      .collect(MoreCollectors.toSet()));
   }
 
   private static ResetRequest toWsRequest(Request request) {
index 99d02ccb6121b45ba1bea8d86638287716a297be..3b2e6c2ee041ed6eea16c1e15b28ff62967df195 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.server.source;
 
 import java.util.Optional;
 import java.util.function.Function;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.protobuf.DbFileSources;
@@ -71,7 +71,7 @@ public class SourceService {
       .filter(line -> line.hasLine() && line.getLine() >= from)
       .limit((toInclusive - from) + 1L)
       .map(function)
-      .collect(Collectors.toList()));
+      .collect(MoreCollectors.toList()));
   }
 
   private static void verifyLine(int line) {
index d09edaa664e405b11128fb505a25fb2fbd2885c9..516849eb8aa6e931ee6180aedc87054bf6cd3290 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.web.page.Page.Qualifier;
 import org.sonar.api.web.page.Page.Scope;
 import org.sonar.api.web.page.PageDefinition;
 import org.sonar.core.platform.PluginRepository;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Collections.emptyList;
@@ -78,7 +78,7 @@ public class PageRepository implements Startable {
       .peek(checkWellFormed())
       .peek(checkPluginExists())
       .sorted(comparing(Page::getKey))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   @Override
@@ -100,7 +100,7 @@ public class PageRepository implements Startable {
       .filter(p -> p.getScope().equals(scope))
       .filter(p -> p.isAdmin() == isAdmin)
       .filter(p -> GLOBAL.equals(p.getScope()) || p.getComponentQualifiers().contains(qualifier))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
   }
 
   @VisibleForTesting
index 478dca4eed3d9742a097deb7c68b2b2ee075a37b..48bff78747f734eee1fa9f5ab5d1517d2f85eb34 100644 (file)
@@ -29,7 +29,7 @@ import java.util.Optional;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -126,7 +126,7 @@ public class ServerUserSession extends AbstractUserSession {
     }
     return permissionKeys.stream()
       .map(OrganizationPermission::fromKey)
-      .collect(Collectors.toSet(permissionKeys.size()));
+      .collect(MoreCollectors.toSet(permissionKeys.size()));
   }
 
   @Override
index 9c253a275c25be774c521ff81847897f7cfc99b7..16bbacf758c9d90af06c5a9cf34412b19112313b 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.platform.NewUserHandler;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationMemberDto;
@@ -340,7 +340,7 @@ public class UserUpdater {
 
   private static List<String> sanitizeScmAccounts(@Nullable List<String> scmAccounts) {
     if (scmAccounts != null) {
-      return scmAccounts.stream().filter(s -> !Strings.isNullOrEmpty(s)).collect(Collectors.toList());
+      return scmAccounts.stream().filter(s -> !Strings.isNullOrEmpty(s)).collect(MoreCollectors.toList());
     }
     return Collections.emptyList();
   }
index 70c1b2eaa80967ee33be3951f0b982ccf95ed336..a3648b6c6c6c7055de884ea8c8d6d83031765c66 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.NewController;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -96,7 +96,7 @@ public class SearchAction implements UserGroupsWsAction {
 
       int limit = dbClient.groupDao().countByQuery(dbSession, organization.getUuid(), query);
       List<GroupDto> groups = dbClient.groupDao().selectByQuery(dbSession, organization.getUuid(), query, options.getOffset(), pageSize);
-      List<Integer> groupIds = groups.stream().map(GroupDto::getId).collect(Collectors.toList(groups.size()));
+      List<Integer> groupIds = groups.stream().map(GroupDto::getId).collect(MoreCollectors.toList(groups.size()));
       Map<String, Integer> userCountByGroup = dbClient.groupMembershipDao().countUsersByGroups(dbSession, groupIds);
 
       JsonWriter json = response.newJsonWriter().beginObject();
index 6a1bd19f46bd50701e4751b529d4d34d318b48d5..d13e62d2656dcff1be736829b2eb4703fb64fc3c 100644 (file)
@@ -30,7 +30,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.web.ServletFilter;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static java.util.stream.Stream.concat;
 import static org.sonar.server.property.ws.PropertiesWs.CONTROLLER_PROPERTIES;
@@ -58,7 +58,7 @@ public class WebServiceFilter extends ServletFilter {
       webServiceEngine.controllers().stream()
         .flatMap(controller -> controller.actions().stream())
         .map(toPath()))
-          .collect(Collectors.toSet());
+          .collect(MoreCollectors.toSet());
     this.excludeUrls = concat(concat(
       Stream.of("/" + CONTROLLER_PROPERTIES + "*"),
       MOVED_WEB_SERVICES.stream()),
@@ -66,7 +66,7 @@ public class WebServiceFilter extends ServletFilter {
         .flatMap(controller -> controller.actions().stream())
         .filter(action -> action.handler() instanceof ServletFilterHandler)
         .map(toPath()))
-          .collect(Collectors.toSet());
+          .collect(MoreCollectors.toSet());
   }
 
   @Override
index 7b20a861a59dfc36f1b4e54e26153abb03e5be39..47f1ad24870adb76d1d675fda78f48240b395fae 100644 (file)
@@ -28,7 +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.utils.text.JsonWriter;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkState;
 
@@ -109,7 +109,7 @@ public class ListAction implements WebServicesWsAction {
   }
 
   private static void writeParameters(JsonWriter writer, WebService.Action action, boolean includeInternals) {
-    List<WebService.Param> params = action.params().stream().filter(p -> includeInternals || !p.isInternal()).collect(Collectors.toList());
+    List<WebService.Param> params = action.params().stream().filter(p -> includeInternals || !p.isInternal()).collect(MoreCollectors.toList());
     if (!params.isEmpty()) {
       // sort parameters by key
       Ordering<WebService.Param> ordering = Ordering.natural().onResultOf(WebService.Param::key);
index 1aa98293e7a0fabb8d7ffb71cd60f06039837274..0cb53e939f63fb6342dc0d8559eb6f16946c2e24 100644 (file)
@@ -35,7 +35,7 @@ import org.sonar.api.config.MapSettings;
 import org.sonar.api.config.Settings;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbTester;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
@@ -424,7 +424,7 @@ public class SsoAuthenticatorTest {
     if (expectedGroups.length == 0) {
       assertThat(db.users().selectGroupIdsOfUser(userDto)).isEmpty();
     } else {
-      assertThat(db.users().selectGroupIdsOfUser(userDto)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(Collectors.toList()).toArray(new Integer[] {}));
+      assertThat(db.users().selectGroupIdsOfUser(userDto)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(MoreCollectors.toList()).toArray(new Integer[] {}));
     }
   }
 
index 373b0ce035e9f627f3421a638744fa9f4cf5b26f..d36d54f66c8aff7af3a022b68bdb9e280e072297 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.server.authentication.UserIdentity;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbTester;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.user.GroupDto;
@@ -267,7 +267,7 @@ public class UserIdentityAuthenticatorTest {
       .setLogin(login)
       .setName("John")
       // No group
-      .setGroups(Arrays.stream(groups).collect(Collectors.toSet()))
+      .setGroups(Arrays.stream(groups).collect(MoreCollectors.toSet()))
       .build(), IDENTITY_PROVIDER, Source.sso());
   }
 
index ca2f975809dc73412ce701f1175ae3fd59dd84c0..78bd13d7f00eecf343e76e0f3a6479a5e84db8f1 100644 (file)
@@ -78,7 +78,7 @@ import static org.sonar.api.server.ws.WebService.Param.PAGE;
 import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
 import static org.sonar.api.server.ws.WebService.Param.SORT;
 import static org.sonar.api.utils.DateUtils.formatDateTime;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 import static org.sonar.db.component.ComponentTesting.newDeveloper;
 import static org.sonar.db.component.ComponentTesting.newDirectory;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
index 229242eeb9715681742dbe7b8ce892bc3b5f6260..e7da1c433fa428febecf3a0cee8dd58e52327945 100644 (file)
@@ -31,7 +31,7 @@ import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -719,7 +719,7 @@ public class SearchActionMediumTest {
     tester.get(PermissionUpdater.class).apply(session, Arrays.stream(permissions)
       // TODO correctly feed default organization. Not a problem as long as issues search does not support "anyone" for each organization
       .map(permission -> new GroupPermissionChange(PermissionChange.Operation.ADD, permission, new ProjectId(project), GroupIdOrAnyone.forAnyone(project.getOrganizationUuid())))
-      .collect(Collectors.toList()));
+      .collect(MoreCollectors.toList()));
   }
 
   private ComponentDto insertComponent(ComponentDto component) {
index 22b9e036f592863d899345ead7c4fbaa9c9a7837..cdf0ecd23f11217086f87f938ee7ff8c353ba5f7 100644 (file)
@@ -33,7 +33,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -181,7 +181,7 @@ public class SearchHistoryActionTest {
       .mapToObj(i -> dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(i * 1_000_000_000)))
       .peek(a -> dbClient.measureDao().insert(dbSession, newMeasureDto(complexityMetric, project, a).setValue(101d)))
       .map(a -> formatDateTime(a.getCreatedAt()))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     db.commit();
     wsRequest.setComponent(project.getKey()).setPage(2).setPageSize(3);
 
@@ -200,7 +200,7 @@ public class SearchHistoryActionTest {
       .mapToObj(i -> dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setCreatedAt(System2.INSTANCE.now() + i * 1_000_000_000L)))
       .peek(a -> dbClient.measureDao().insert(dbSession, newMeasureDto(complexityMetric, project, a).setValue(Double.valueOf(a.getCreatedAt()))))
       .map(a -> formatDateTime(a.getCreatedAt()))
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     db.commit();
     wsRequest.setComponent(project.getKey()).setFrom(analysisDates.get(1)).setTo(analysisDates.get(3));
 
index 004cc7cc965bcbea84e44e699f73cbb08ab515ed..c117cab5d3246ecafbf27cb9aa9936af45059bde 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Arrays;
 import java.util.List;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHits;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.server.es.EsClient;
 
 import static org.sonar.server.permission.index.FooIndexDefinition.FOO_INDEX;
@@ -49,7 +49,7 @@ public class FooIndex {
       .getHits();
     List<String> names = Arrays.stream(hits.hits())
       .map(h -> h.getSource().get(FooIndexDefinition.FIELD_NAME).toString())
-      .collect(Collectors.toList());
+      .collect(MoreCollectors.toList());
     return names.size() == 2 && names.contains("bar") && names.contains("baz");
   }
 }
index b39d94c0224909c2d3ed9ccbceabe91274ba8bf2..6b88025dd53308866a8fdb75b3132b3958d8229f 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -121,7 +121,7 @@ public class PermissionIndexerDaoTest {
 
     Map<String, PermissionIndexerDao.Dto> dtos = underTest.selectByUuids(dbClient, dbSession, asList(project1.uuid(), project2.uuid(), view1.uuid(), view2.uuid()))
       .stream()
-      .collect(Collectors.uniqueIndex(PermissionIndexerDao.Dto::getProjectUuid, Function.identity()));
+      .collect(MoreCollectors.uniqueIndex(PermissionIndexerDao.Dto::getProjectUuid, Function.identity()));
     assertThat(dtos).hasSize(4);
 
     PermissionIndexerDao.Dto project1Authorization = dtos.get(project1.uuid());
@@ -171,7 +171,7 @@ public class PermissionIndexerDaoTest {
 
     Map<String, PermissionIndexerDao.Dto> dtos = underTest.selectByUuids(dbClient, dbSession, projects)
       .stream()
-      .collect(Collectors.uniqueIndex(PermissionIndexerDao.Dto::getProjectUuid, Function.identity()));
+      .collect(MoreCollectors.uniqueIndex(PermissionIndexerDao.Dto::getProjectUuid, Function.identity()));
     assertThat(dtos).hasSize(350);
   }
 
index 7622a437294b2f91a4649f717135b4117f77bc4f..0f449bd6f1e88192a3919ea4906d5576ef59139e 100644 (file)
@@ -40,7 +40,7 @@ import org.sonar.api.rules.RuleParam;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -273,7 +273,7 @@ public class DefinedQProfileCreationImplTest {
     rule.setParams(Arrays.stream(parameters)
       .filter(new EvenElementPredicate())
       .map(s -> new RuleParam(rule, s, "desc of s", "type of s"))
-      .collect(Collectors.toList(parameters.length / 2)));
+      .collect(MoreCollectors.toList(parameters.length / 2)));
     ActiveRule res = new ActiveRule(
       new RulesProfile("rule_profile_name_" + id, "language_" + id),
       rule.setSeverity(rulePriority),
index 83ecacb5588c9d080b08f22994b6e3c8749c3682..65a6091a7b618296cede5d1a88f36cc8747ef24e 100644 (file)
@@ -29,10 +29,10 @@ import java.util.stream.Stream;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.junit.rules.ExternalResource;
 import org.sonar.api.resources.Language;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 
 import static com.google.common.base.Preconditions.checkState;
-import static org.sonar.core.util.stream.Collectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
 
 public class DefinedQProfileRepositoryRule extends ExternalResource implements DefinedQProfileRepository {
   private boolean initializeCalled = false;
@@ -79,7 +79,7 @@ public class DefinedQProfileRepositoryRule extends ExternalResource implements D
         if (existing == null) {
           return ImmutableList.of(definedQProfile);
         }
-        return Stream.concat(existing.stream(), Stream.of(definedQProfile)).collect(Collectors.toList(existing.size() + 1));
+        return Stream.concat(existing.stream(), Stream.of(definedQProfile)).collect(MoreCollectors.toList(existing.size() + 1));
       });
     return definedQProfile;
   }
index 279191e3a1b1e12a44e3c88d8a7429825ea8716b..faf25a4e75b11102bb79c907099b395ae5ab3ac0 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
@@ -190,7 +190,7 @@ public class ChangeParentActionTest {
     RuleDto rule2 = createRule();
     createActiveRule(rule1, parent1);
     createActiveRule(rule2, parent2);
-    ruleIndexer.index(organization, Stream.of(rule1, rule2).map(RuleDto::getKey).collect(Collectors.toList()));
+    ruleIndexer.index(organization, Stream.of(rule1, rule2).map(RuleDto::getKey).collect(MoreCollectors.toList()));
     activeRuleIndexer.index();
 
     // Set parent 1
index 509b8a59f935cb3f3a53f0e5ed5b81dd01c509c8..c979889d3738c3372eb5a303edb4cb733acf5bf9 100644 (file)
@@ -28,7 +28,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.organization.OrganizationDto;
@@ -155,7 +155,7 @@ public class RulesWsMediumTest {
     ruleDao.insertOrUpdate(session, rule2.getMetadata().setRuleId(rule2.getId()));
 
     session.commit();
-    ruleIndexer.index(defaultOrganization, Stream.of(rule, rule2).map(RuleDto::getKey).collect(Collectors.toList()));
+    ruleIndexer.index(defaultOrganization, Stream.of(rule, rule2).map(RuleDto::getKey).collect(MoreCollectors.toList()));
 
     tester.wsTester().newGetRequest(API_ENDPOINT, API_TAGS_METHOD).execute().assertJson(this.getClass(), "get_tags.json");
     tester.wsTester().newGetRequest(API_ENDPOINT, API_TAGS_METHOD)
index 2a67bc6bf8a1be106dcb91f6dfd686d91415352b..6406336c580abf408a80298d7c57e1e04c709bf6 100644 (file)
@@ -63,7 +63,7 @@ import static org.sonar.api.measures.CoreMetrics.TEST_EXECUTION_TIME;
 import static org.sonar.api.measures.CoreMetrics.TEST_FAILURES;
 import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS;
 import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES;
-import static org.sonar.core.util.stream.Collectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
 
 /**
  * This class is used to know the list of metrics that can be sent in the analysis report.
diff --git a/sonar-core/src/main/java/org/sonar/core/util/stream/Collectors.java b/sonar-core/src/main/java/org/sonar/core/util/stream/Collectors.java
deleted file mode 100644 (file)
index ae28d03..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.core.util.stream;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.BinaryOperator;
-import java.util.function.Function;
-import java.util.function.Supplier;
-import java.util.stream.Collector;
-
-import static java.util.Objects.requireNonNull;
-
-public final class Collectors {
-
-  private static final int DEFAULT_HASHMAP_CAPACITY = 0;
-
-  private Collectors() {
-    // prevents instantiation
-  }
-
-  /**
-   * A Collector into an {@link ImmutableList}.
-   */
-  public static <T> Collector<T, List<T>, List<T>> toList() {
-    return Collector.of(
-      ArrayList::new,
-      List::add,
-      (left, right) -> {
-        left.addAll(right);
-        return left;
-      },
-      ImmutableList::copyOf);
-  }
-
-  /**
-   * A Collector into an {@link ImmutableList} of the specified expected size.
-   *
-   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
-   * processing threads will use a List with a capacity large enough for the final size.</p>
-   */
-  public static <T> Collector<T, List<T>, List<T>> toList(int expectedSize) {
-    // use ArrayList rather than ImmutableList.Builder because initial capacity of builder can not be specified
-    return Collector.of(
-      () -> new ArrayList<>(expectedSize),
-      List::add,
-      (left, right) -> {
-        left.addAll(right);
-        return left;
-      },
-      ImmutableList::copyOf);
-  }
-
-  /**
-   * A Collector into an {@link ImmutableSet}.
-   */
-  public static <T> Collector<T, Set<T>, Set<T>> toSet() {
-    return Collector.of(
-      HashSet::new,
-      Set::add,
-      (left, right) -> {
-        left.addAll(right);
-        return left;
-      },
-      ImmutableSet::copyOf);
-  }
-
-  /**
-   * A Collector into an {@link ImmutableSet} of the specified expected size.
-   *
-   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
-   * processing threads will use a Set with a capacity large enough for the final size.</p>
-   */
-  public static <T> Collector<T, Set<T>, Set<T>> toSet(int expectedSize) {
-    // use HashSet rather than ImmutableSet.Builder because initial capacity of builder can not be specified
-    return Collector.of(
-      () -> new HashSet<>(expectedSize),
-      Set::add,
-      (left, right) -> {
-        left.addAll(right);
-        return left;
-      },
-      ImmutableSet::copyOf);
-  }
-
-  /**
-   * Delegates to {@link java.util.stream.Collectors#toCollection(Supplier)}.
-   */
-  public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
-    return java.util.stream.Collectors.toCollection(ArrayList::new);
-  }
-
-  /**
-   * Does {@code java.util.stream.Collectors.toCollection(() -> new ArrayList<>(size));} which is equivalent to
-   * {@link #toArrayList()} but avoiding array copies when the size of the resulting list is already known.
-   *
-   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
-   * processing threads will use a ArrayList with a capacity large enough for the final size.</p>
-   *
-   * @see java.util.stream.Collectors#toList()
-   * @see java.util.stream.Collectors#toCollection(Supplier)
-   */
-  public static <T> Collector<T, ?, ArrayList<T>> toArrayList(int size) {
-    return java.util.stream.Collectors.toCollection(() -> new ArrayList<>(size));
-  }
-
-  /**
-   * Delegates to {@link java.util.stream.Collectors#toCollection(Supplier)}.
-   */
-  public static <T> Collector<T, ?, HashSet<T>> toHashSet() {
-    return java.util.stream.Collectors.toCollection(HashSet::new);
-  }
-
-  /**
-   * Does {@code java.util.stream.Collectors.toCollection(() -> new HashSet<>(size));} which is equivalent to
-   * {@link #toHashSet()} but avoiding array copies when the size of the resulting set is already known.
-   *
-   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
-   * processing threads will use a HashSet with a capacity large enough for the final size.</p>
-   *
-   * @see java.util.stream.Collectors#toSet()
-   * @see java.util.stream.Collectors#toCollection(Supplier)
-   */
-  public static <T> Collector<T, ?, HashSet<T>> toHashSet(int size) {
-    return java.util.stream.Collectors.toCollection(() -> new HashSet<>(size));
-  }
-
-  /**
-   * Creates an {@link ImmutableMap} from the stream where the values are the values in the stream and the keys are the
-   * result of the provided {@link Function keyFunction} applied to each value in the stream.
-   *
-   * <p>
-   * The {@link Function keyFunction} must return a unique (according to the key's type {@link Object#equals(Object)}
-   * and/or {@link Comparable#compareTo(Object)} implementations) value for each of them, otherwise a
-   * {@link IllegalArgumentException} will be thrown.
-   * </p>
-   *
-   * <p>
-   * {@link Function keyFunction} can't return {@code null}, otherwise a {@link NullPointerException} will be thrown.
-   * </p>
-   *
-   * @throws NullPointerException if {@code keyFunction} is {@code null}.
-   * @throws NullPointerException if result of {@code keyFunction} is {@code null}.
-   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
-   */
-  public static <K, E> Collector<E, Map<K, E>, ImmutableMap<K, E>> uniqueIndex(Function<? super E, K> keyFunction) {
-    return uniqueIndex(keyFunction, Function.<E>identity());
-  }
-
-  /**
-   * Same as {@link #uniqueIndex(Function)} but using an underlying {@link Map} initialized with a capacity for the
-   * specified expected size.
-   *
-   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
-   * processing threads will use a Map with a capacity large enough for the final size.</p>
-   *
-   * <p>
-   * {@link Function keyFunction} can't return {@code null}, otherwise a {@link NullPointerException} will be thrown.
-   * </p>
-   *
-   * @throws NullPointerException if {@code keyFunction} is {@code null}.
-   * @throws NullPointerException if result of {@code keyFunction} is {@code null}.
-   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
-   * @see #uniqueIndex(Function)
-   */
-  public static <K, E> Collector<E, Map<K, E>, ImmutableMap<K, E>> uniqueIndex(Function<? super E, K> keyFunction, int expectedSize) {
-    return uniqueIndex(keyFunction, Function.<E>identity(), expectedSize);
-  }
-
-  /**
-   * Creates an {@link ImmutableMap} from the stream where the values are the result of {@link Function valueFunction}
-   * applied to the values in the stream and the keys are the result of the provided {@link Function keyFunction}
-   * applied to each value in the stream.
-   *
-   * <p>
-   * The {@link Function keyFunction} must return a unique (according to the key's type {@link Object#equals(Object)}
-   * and/or {@link Comparable#compareTo(Object)} implementations) value for each of them, otherwise a
-   * {@link IllegalArgumentException} will be thrown.
-   * </p>
-   *
-   * <p>
-   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
-   * {@link NullPointerException} will be thrown.
-   * </p>
-   *
-   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
-   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
-   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
-   */
-  public static <K, E, V> Collector<E, Map<K, V>, ImmutableMap<K, V>> uniqueIndex(Function<? super E, K> keyFunction,
-    Function<? super E, V> valueFunction) {
-    return uniqueIndex(keyFunction, valueFunction, DEFAULT_HASHMAP_CAPACITY);
-  }
-
-  /**
-   * Same as {@link #uniqueIndex(Function, Function)} but using an underlying {@link Map} initialized with a capacity
-   * for the specified expected size.
-   *
-   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
-   * processing threads will use a Map with a capacity large enough for the final size.</p>
-   *
-   * <p>
-   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
-   * {@link NullPointerException} will be thrown.
-   * </p>
-   *
-   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
-   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
-   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
-   * @see #uniqueIndex(Function, Function)
-   */
-  public static <K, E, V> Collector<E, Map<K, V>, ImmutableMap<K, V>> uniqueIndex(Function<? super E, K> keyFunction,
-    Function<? super E, V> valueFunction, int expectedSize) {
-    requireNonNull(keyFunction, "Key function can't be null");
-    requireNonNull(valueFunction, "Value function can't be null");
-    BiConsumer<Map<K, V>, E> accumulator = (map, element) -> {
-      K key = requireNonNull(keyFunction.apply(element), "Key function can't return null");
-      V value = requireNonNull(valueFunction.apply(element), "Value function can't return null");
-
-      putAndFailOnDuplicateKey(map, key, value);
-    };
-    BinaryOperator<Map<K, V>> merger = (m1, m2) -> {
-      for (Map.Entry<K, V> entry : m2.entrySet()) {
-        putAndFailOnDuplicateKey(m1, entry.getKey(), entry.getValue());
-      }
-      return m1;
-    };
-    return Collector.of(
-      newHashMapSupplier(expectedSize),
-      accumulator,
-      merger,
-      ImmutableMap::copyOf,
-      Collector.Characteristics.UNORDERED);
-  }
-
-  /**
-   * For stream of one expected element, return the element
-   *
-   * @throws IllegalArgumentException if stream has no element or more than 1 element
-   */
-  public static <T> Collector<T, ?, T> toOneElement() {
-    return java.util.stream.Collectors.collectingAndThen(
-      java.util.stream.Collectors.toList(),
-      list -> {
-        if (list.size() != 1) {
-          throw new IllegalStateException("Stream should have only one element");
-        }
-        return list.get(0);
-      });
-  }
-
-  private static <K, V> Supplier<Map<K, V>> newHashMapSupplier(int expectedSize) {
-    return () -> expectedSize == DEFAULT_HASHMAP_CAPACITY ? new HashMap<>() : new HashMap<>(expectedSize);
-  }
-
-  private static <K, V> void putAndFailOnDuplicateKey(Map<K, V> map, K key, V value) {
-    V existingValue = map.put(key, value);
-    if (existingValue != null) {
-      throw new IllegalArgumentException(String.format("Duplicate key %s", key));
-    }
-  }
-
-  /**
-   * Creates an {@link com.google.common.collect.ImmutableListMultimap} from the stream where the values are the values
-   * in the stream and the keys are the result of the provided {@link Function keyFunction} applied to each value in the
-   * stream.
-   *
-   * <p>
-   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
-   * {@link NullPointerException} will be thrown.
-   * </p>
-   *
-   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
-   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
-   */
-  public static <K, E> Collector<E, ImmutableListMultimap.Builder<K, E>, ImmutableListMultimap<K, E>> index(Function<? super E, K> keyFunction) {
-    return index(keyFunction, Function.<E>identity());
-  }
-
-  /**
-   * Creates an {@link com.google.common.collect.ImmutableListMultimap} from the stream where the values are the result
-   * of {@link Function valueFunction} applied to the values in the stream and the keys are the result of the provided
-   * {@link Function keyFunction} applied to each value in the stream.
-   *
-   * <p>
-   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
-   * {@link NullPointerException} will be thrown.
-   * </p>
-   *
-   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
-   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
-   */
-  public static <K, E, V> Collector<E, ImmutableListMultimap.Builder<K, V>, ImmutableListMultimap<K, V>> index(Function<? super E, K> keyFunction,
-    Function<? super E, V> valueFunction) {
-    requireNonNull(keyFunction, "Key function can't be null");
-    requireNonNull(valueFunction, "Value function can't be null");
-    BiConsumer<ImmutableListMultimap.Builder<K, V>, E> accumulator = (map, element) -> {
-      K key = requireNonNull(keyFunction.apply(element), "Key function can't return null");
-      V value = requireNonNull(valueFunction.apply(element), "Value function can't return null");
-
-      map.put(key, value);
-    };
-    BinaryOperator<ImmutableListMultimap.Builder<K, V>> merger = (m1, m2) -> {
-      for (Map.Entry<K, V> entry : m2.build().entries()) {
-        m1.put(entry.getKey(), entry.getValue());
-      }
-      return m1;
-    };
-    return Collector.of(
-      ImmutableListMultimap::builder,
-      accumulator,
-      merger,
-      ImmutableListMultimap.Builder::build);
-  }
-
-  /**
-   * Applies the specified {@link Joiner} to the current stream.
-   *
-   * @throws NullPointerException of {@code joiner} is {@code null}
-   * @throws IllegalStateException if a merge operation happens because parallel processing has been enabled on the current stream
-   */
-  public static <E> Collector<E, List<E>, String> join(Joiner joiner) {
-    requireNonNull(joiner, "Joiner can't be null");
-
-    return Collector.of(
-      ArrayList::new,
-      List::add,
-      mergeNotSupportedMerger(),
-      joiner::join);
-  }
-
-  private static <R> BinaryOperator<R> mergeNotSupportedMerger() {
-    return (m1, m2) -> {
-      throw new IllegalStateException("Parallel processing is not supported");
-    };
-  }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/util/stream/MoreCollectors.java b/sonar-core/src/main/java/org/sonar/core/util/stream/MoreCollectors.java
new file mode 100644 (file)
index 0000000..64616cf
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.stream;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import static java.util.Objects.requireNonNull;
+
+public final class MoreCollectors {
+
+  private static final int DEFAULT_HASHMAP_CAPACITY = 0;
+
+  private MoreCollectors() {
+    // prevents instantiation
+  }
+
+  /**
+   * A Collector into an {@link ImmutableList}.
+   */
+  public static <T> Collector<T, List<T>, List<T>> toList() {
+    return Collector.of(
+      ArrayList::new,
+      List::add,
+      (left, right) -> {
+        left.addAll(right);
+        return left;
+      },
+      ImmutableList::copyOf);
+  }
+
+  /**
+   * A Collector into an {@link ImmutableList} of the specified expected size.
+   *
+   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
+   * processing threads will use a List with a capacity large enough for the final size.</p>
+   */
+  public static <T> Collector<T, List<T>, List<T>> toList(int expectedSize) {
+    // use ArrayList rather than ImmutableList.Builder because initial capacity of builder can not be specified
+    return Collector.of(
+      () -> new ArrayList<>(expectedSize),
+      List::add,
+      (left, right) -> {
+        left.addAll(right);
+        return left;
+      },
+      ImmutableList::copyOf);
+  }
+
+  /**
+   * A Collector into an {@link ImmutableSet}.
+   */
+  public static <T> Collector<T, Set<T>, Set<T>> toSet() {
+    return Collector.of(
+      HashSet::new,
+      Set::add,
+      (left, right) -> {
+        left.addAll(right);
+        return left;
+      },
+      ImmutableSet::copyOf);
+  }
+
+  /**
+   * A Collector into an {@link ImmutableSet} of the specified expected size.
+   *
+   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
+   * processing threads will use a Set with a capacity large enough for the final size.</p>
+   */
+  public static <T> Collector<T, Set<T>, Set<T>> toSet(int expectedSize) {
+    // use HashSet rather than ImmutableSet.Builder because initial capacity of builder can not be specified
+    return Collector.of(
+      () -> new HashSet<>(expectedSize),
+      Set::add,
+      (left, right) -> {
+        left.addAll(right);
+        return left;
+      },
+      ImmutableSet::copyOf);
+  }
+
+  /**
+   * Delegates to {@link java.util.stream.Collectors#toCollection(Supplier)}.
+   */
+  public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
+    return java.util.stream.Collectors.toCollection(ArrayList::new);
+  }
+
+  /**
+   * Does {@code java.util.stream.MoreCollectors.toCollection(() -> new ArrayList<>(size));} which is equivalent to
+   * {@link #toArrayList()} but avoiding array copies when the size of the resulting list is already known.
+   *
+   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
+   * processing threads will use a ArrayList with a capacity large enough for the final size.</p>
+   *
+   * @see java.util.stream.Collectors#toList()
+   * @see java.util.stream.Collectors#toCollection(Supplier)
+   */
+  public static <T> Collector<T, ?, ArrayList<T>> toArrayList(int size) {
+    return java.util.stream.Collectors.toCollection(() -> new ArrayList<>(size));
+  }
+
+  /**
+   * Delegates to {@link java.util.stream.Collectors#toCollection(Supplier)}.
+   */
+  public static <T> Collector<T, ?, HashSet<T>> toHashSet() {
+    return java.util.stream.Collectors.toCollection(HashSet::new);
+  }
+
+  /**
+   * Does {@code java.util.stream.MoreCollectors.toCollection(() -> new HashSet<>(size));} which is equivalent to
+   * {@link #toHashSet()} but avoiding array copies when the size of the resulting set is already known.
+   *
+   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
+   * processing threads will use a HashSet with a capacity large enough for the final size.</p>
+   *
+   * @see java.util.stream.Collectors#toSet()
+   * @see java.util.stream.Collectors#toCollection(Supplier)
+   */
+  public static <T> Collector<T, ?, HashSet<T>> toHashSet(int size) {
+    return java.util.stream.Collectors.toCollection(() -> new HashSet<>(size));
+  }
+
+  /**
+   * Creates an {@link ImmutableMap} from the stream where the values are the values in the stream and the keys are the
+   * result of the provided {@link Function keyFunction} applied to each value in the stream.
+   *
+   * <p>
+   * The {@link Function keyFunction} must return a unique (according to the key's type {@link Object#equals(Object)}
+   * and/or {@link Comparable#compareTo(Object)} implementations) value for each of them, otherwise a
+   * {@link IllegalArgumentException} will be thrown.
+   * </p>
+   *
+   * <p>
+   * {@link Function keyFunction} can't return {@code null}, otherwise a {@link NullPointerException} will be thrown.
+   * </p>
+   *
+   * @throws NullPointerException if {@code keyFunction} is {@code null}.
+   * @throws NullPointerException if result of {@code keyFunction} is {@code null}.
+   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
+   */
+  public static <K, E> Collector<E, Map<K, E>, ImmutableMap<K, E>> uniqueIndex(Function<? super E, K> keyFunction) {
+    return uniqueIndex(keyFunction, Function.<E>identity());
+  }
+
+  /**
+   * Same as {@link #uniqueIndex(Function)} but using an underlying {@link Map} initialized with a capacity for the
+   * specified expected size.
+   *
+   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
+   * processing threads will use a Map with a capacity large enough for the final size.</p>
+   *
+   * <p>
+   * {@link Function keyFunction} can't return {@code null}, otherwise a {@link NullPointerException} will be thrown.
+   * </p>
+   *
+   * @throws NullPointerException if {@code keyFunction} is {@code null}.
+   * @throws NullPointerException if result of {@code keyFunction} is {@code null}.
+   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
+   * @see #uniqueIndex(Function)
+   */
+  public static <K, E> Collector<E, Map<K, E>, ImmutableMap<K, E>> uniqueIndex(Function<? super E, K> keyFunction, int expectedSize) {
+    return uniqueIndex(keyFunction, Function.<E>identity(), expectedSize);
+  }
+
+  /**
+   * Creates an {@link ImmutableMap} from the stream where the values are the result of {@link Function valueFunction}
+   * applied to the values in the stream and the keys are the result of the provided {@link Function keyFunction}
+   * applied to each value in the stream.
+   *
+   * <p>
+   * The {@link Function keyFunction} must return a unique (according to the key's type {@link Object#equals(Object)}
+   * and/or {@link Comparable#compareTo(Object)} implementations) value for each of them, otherwise a
+   * {@link IllegalArgumentException} will be thrown.
+   * </p>
+   *
+   * <p>
+   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
+   * {@link NullPointerException} will be thrown.
+   * </p>
+   *
+   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
+   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
+   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
+   */
+  public static <K, E, V> Collector<E, Map<K, V>, ImmutableMap<K, V>> uniqueIndex(Function<? super E, K> keyFunction,
+    Function<? super E, V> valueFunction) {
+    return uniqueIndex(keyFunction, valueFunction, DEFAULT_HASHMAP_CAPACITY);
+  }
+
+  /**
+   * Same as {@link #uniqueIndex(Function, Function)} but using an underlying {@link Map} initialized with a capacity
+   * for the specified expected size.
+   *
+   * <p>Note: using this method with a parallel stream will likely not have the expected memory usage benefit as all
+   * processing threads will use a Map with a capacity large enough for the final size.</p>
+   *
+   * <p>
+   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
+   * {@link NullPointerException} will be thrown.
+   * </p>
+   *
+   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
+   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
+   * @throws IllegalArgumentException if {@code keyFunction} returns the same value for multiple entries in the stream.
+   * @see #uniqueIndex(Function, Function)
+   */
+  public static <K, E, V> Collector<E, Map<K, V>, ImmutableMap<K, V>> uniqueIndex(Function<? super E, K> keyFunction,
+    Function<? super E, V> valueFunction, int expectedSize) {
+    requireNonNull(keyFunction, "Key function can't be null");
+    requireNonNull(valueFunction, "Value function can't be null");
+    BiConsumer<Map<K, V>, E> accumulator = (map, element) -> {
+      K key = requireNonNull(keyFunction.apply(element), "Key function can't return null");
+      V value = requireNonNull(valueFunction.apply(element), "Value function can't return null");
+
+      putAndFailOnDuplicateKey(map, key, value);
+    };
+    BinaryOperator<Map<K, V>> merger = (m1, m2) -> {
+      for (Map.Entry<K, V> entry : m2.entrySet()) {
+        putAndFailOnDuplicateKey(m1, entry.getKey(), entry.getValue());
+      }
+      return m1;
+    };
+    return Collector.of(
+      newHashMapSupplier(expectedSize),
+      accumulator,
+      merger,
+      ImmutableMap::copyOf,
+      Collector.Characteristics.UNORDERED);
+  }
+
+  /**
+   * For stream of one expected element, return the element
+   *
+   * @throws IllegalArgumentException if stream has no element or more than 1 element
+   */
+  public static <T> Collector<T, ?, T> toOneElement() {
+    return java.util.stream.Collectors.collectingAndThen(
+      java.util.stream.Collectors.toList(),
+      list -> {
+        if (list.size() != 1) {
+          throw new IllegalStateException("Stream should have only one element");
+        }
+        return list.get(0);
+      });
+  }
+
+  private static <K, V> Supplier<Map<K, V>> newHashMapSupplier(int expectedSize) {
+    return () -> expectedSize == DEFAULT_HASHMAP_CAPACITY ? new HashMap<>() : new HashMap<>(expectedSize);
+  }
+
+  private static <K, V> void putAndFailOnDuplicateKey(Map<K, V> map, K key, V value) {
+    V existingValue = map.put(key, value);
+    if (existingValue != null) {
+      throw new IllegalArgumentException(String.format("Duplicate key %s", key));
+    }
+  }
+
+  /**
+   * Creates an {@link com.google.common.collect.ImmutableListMultimap} from the stream where the values are the values
+   * in the stream and the keys are the result of the provided {@link Function keyFunction} applied to each value in the
+   * stream.
+   *
+   * <p>
+   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
+   * {@link NullPointerException} will be thrown.
+   * </p>
+   *
+   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
+   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
+   */
+  public static <K, E> Collector<E, ImmutableListMultimap.Builder<K, E>, ImmutableListMultimap<K, E>> index(Function<? super E, K> keyFunction) {
+    return index(keyFunction, Function.<E>identity());
+  }
+
+  /**
+   * Creates an {@link com.google.common.collect.ImmutableListMultimap} from the stream where the values are the result
+   * of {@link Function valueFunction} applied to the values in the stream and the keys are the result of the provided
+   * {@link Function keyFunction} applied to each value in the stream.
+   *
+   * <p>
+   * Neither {@link Function keyFunction} nor {@link Function valueFunction} can return {@code null}, otherwise a
+   * {@link NullPointerException} will be thrown.
+   * </p>
+   *
+   * @throws NullPointerException if {@code keyFunction} or {@code valueFunction} is {@code null}.
+   * @throws NullPointerException if result of {@code keyFunction} or {@code valueFunction} is {@code null}.
+   */
+  public static <K, E, V> Collector<E, ImmutableListMultimap.Builder<K, V>, ImmutableListMultimap<K, V>> index(Function<? super E, K> keyFunction,
+    Function<? super E, V> valueFunction) {
+    requireNonNull(keyFunction, "Key function can't be null");
+    requireNonNull(valueFunction, "Value function can't be null");
+    BiConsumer<ImmutableListMultimap.Builder<K, V>, E> accumulator = (map, element) -> {
+      K key = requireNonNull(keyFunction.apply(element), "Key function can't return null");
+      V value = requireNonNull(valueFunction.apply(element), "Value function can't return null");
+
+      map.put(key, value);
+    };
+    BinaryOperator<ImmutableListMultimap.Builder<K, V>> merger = (m1, m2) -> {
+      for (Map.Entry<K, V> entry : m2.build().entries()) {
+        m1.put(entry.getKey(), entry.getValue());
+      }
+      return m1;
+    };
+    return Collector.of(
+      ImmutableListMultimap::builder,
+      accumulator,
+      merger,
+      ImmutableListMultimap.Builder::build);
+  }
+
+  /**
+   * Applies the specified {@link Joiner} to the current stream.
+   *
+   * @throws NullPointerException of {@code joiner} is {@code null}
+   * @throws IllegalStateException if a merge operation happens because parallel processing has been enabled on the current stream
+   */
+  public static <E> Collector<E, List<E>, String> join(Joiner joiner) {
+    requireNonNull(joiner, "Joiner can't be null");
+
+    return Collector.of(
+      ArrayList::new,
+      List::add,
+      mergeNotSupportedMerger(),
+      joiner::join);
+  }
+
+  private static <R> BinaryOperator<R> mergeNotSupportedMerger() {
+    return (m1, m2) -> {
+      throw new IllegalStateException("Parallel processing is not supported");
+    };
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/stream/CollectorsTest.java b/sonar-core/src/test/java/org/sonar/core/util/stream/CollectorsTest.java
deleted file mode 100644 (file)
index d15ae53..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-package org.sonar.core.util.stream;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static java.util.function.Function.identity;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.entry;
-import static org.sonar.core.util.stream.Collectors.index;
-import static org.sonar.core.util.stream.Collectors.join;
-import static org.sonar.core.util.stream.Collectors.toArrayList;
-import static org.sonar.core.util.stream.Collectors.toHashSet;
-import static org.sonar.core.util.stream.Collectors.toList;
-import static org.sonar.core.util.stream.Collectors.toSet;
-import static org.sonar.core.util.stream.Collectors.uniqueIndex;
-
-public class CollectorsTest {
-
-  private static final List<String> HUGE_LIST = IntStream.range(0, 2_000).mapToObj(String::valueOf).collect(java.util.stream.Collectors.toList());
-  private static final Set<String> HUGE_SET = new HashSet<>(HUGE_LIST);
-  private static final MyObj MY_OBJ_1_A = new MyObj(1, "A");
-  private static final MyObj MY_OBJ_1_C = new MyObj(1, "C");
-  private static final MyObj MY_OBJ_2_B = new MyObj(2, "B");
-  private static final MyObj MY_OBJ_3_C = new MyObj(3, "C");
-  private static final List<MyObj> SINGLE_ELEMENT_LIST = Arrays.asList(MY_OBJ_1_A);
-  private static final List<MyObj> LIST_WITH_DUPLICATE_ID = Arrays.asList(MY_OBJ_1_A, MY_OBJ_2_B, MY_OBJ_1_C);
-  private static final List<MyObj> LIST = Arrays.asList(MY_OBJ_1_A, MY_OBJ_2_B, MY_OBJ_3_C);
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void toList_builds_an_ImmutableList() {
-    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toList());
-    assertThat(res).isInstanceOf(ImmutableList.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toList_parallel_stream() {
-    assertThat(HUGE_LIST.parallelStream().collect(toList())).isEqualTo(HUGE_LIST);
-  }
-
-  @Test
-  public void toList_with_size_builds_an_ImmutableList() {
-    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toList(30));
-    assertThat(res).isInstanceOf(ImmutableList.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toList_with_size_parallel_stream() {
-    assertThat(HUGE_LIST.parallelStream().collect(toList(HUGE_LIST.size()))).isEqualTo(HUGE_LIST);
-  }
-
-  @Test
-  public void toSet_builds_an_ImmutableSet() {
-    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toSet());
-    assertThat(res).isInstanceOf(ImmutableSet.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toSet_parallel_stream() {
-    assertThat(HUGE_SET.parallelStream().collect(toSet())).isEqualTo(HUGE_SET);
-  }
-
-  @Test
-  public void toSet_with_size_builds_an_ImmutableSet() {
-    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toSet(30));
-    assertThat(res).isInstanceOf(ImmutableSet.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toSet_with_size_parallel_stream() {
-    assertThat(HUGE_SET.parallelStream().collect(toSet(HUGE_SET.size()))).isEqualTo(HUGE_SET);
-  }
-
-  @Test
-  public void toArrayList_builds_an_ArrayList() {
-    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toArrayList());
-    assertThat(res).isInstanceOf(ArrayList.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toArrayList_parallel_stream() {
-    assertThat(HUGE_LIST.parallelStream().collect(toArrayList())).isEqualTo(HUGE_LIST);
-  }
-
-  @Test
-  public void toArrayList_with_size_builds_an_ArrayList() {
-    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toArrayList(30));
-    assertThat(res).isInstanceOf(ArrayList.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toArrayList_with_size_parallel_stream() {
-    assertThat(HUGE_LIST.parallelStream().collect(toArrayList(HUGE_LIST.size()))).isEqualTo(HUGE_LIST);
-  }
-
-  @Test
-  public void toHashSet_builds_an_HashSet() {
-    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toHashSet());
-    assertThat(res).isInstanceOf(HashSet.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toHashSet_parallel_stream() {
-    assertThat(HUGE_SET.parallelStream().collect(toHashSet())).isEqualTo(HUGE_SET);
-  }
-
-  @Test
-  public void toHashSet_with_size_builds_an_ArrayList() {
-    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toHashSet(30));
-    assertThat(res).isInstanceOf(HashSet.class)
-      .containsExactly(1, 2, 3, 4, 5);
-  }
-
-  @Test
-  public void toHashSet_with_size_parallel_stream() {
-    assertThat(HUGE_SET.parallelStream().collect(toHashSet(HUGE_SET.size()))).isEqualTo(HUGE_SET);
-  }
-
-  @Test
-  public void uniqueIndex_empty_stream_returns_empty_map() {
-    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId))).isEmpty();
-    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId, 6))).isEmpty();
-    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId, MyObj::getText))).isEmpty();
-    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId, MyObj::getText, 10))).isEmpty();
-  }
-
-  @Test
-  public void uniqueIndex_fails_when_there_is_duplicate_keys() {
-    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
-
-    expectedDuplicateKey1IAE();
-
-    stream.collect(uniqueIndex(MyObj::getId));
-  }
-
-  @Test
-  public void uniqueIndex_with_expected_size_fails_when_there_is_duplicate_keys() {
-    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
-
-    expectedDuplicateKey1IAE();
-
-    stream.collect(uniqueIndex(MyObj::getId, 1));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_fails_when_there_is_duplicate_keys() {
-    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
-
-    expectedDuplicateKey1IAE();
-
-    stream.collect(uniqueIndex(MyObj::getId, MyObj::getText));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_fails_when_there_is_duplicate_keys() {
-    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
-
-    expectedDuplicateKey1IAE();
-
-    stream.collect(uniqueIndex(MyObj::getId, MyObj::getText, 10));
-  }
-
-  @Test
-  public void uniqueIndex_fails_if_key_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't be null");
-
-    uniqueIndex(null);
-  }
-
-  @Test
-  public void uniqueIndex_with_expected_size_fails_if_key_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't be null");
-
-    uniqueIndex(null, 2);
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_fails_if_key_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't be null");
-
-    uniqueIndex(null, MyObj::getText);
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_key_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't be null");
-
-    uniqueIndex(null, MyObj::getText, 9);
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_fails_if_value_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Value function can't be null");
-
-    uniqueIndex(MyObj::getId, null);
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_value_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Value function can't be null");
-
-    uniqueIndex(MyObj::getId, null, 9);
-  }
-
-  @Test
-  public void uniqueIndex_fails_if_key_function_returns_null() {
-    expectKeyFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null));
-  }
-
-  @Test
-  public void uniqueIndex_with_expected_size_fails_if_key_function_returns_null() {
-    expectKeyFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null, 90));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_fails_if_key_function_returns_null() {
-    expectKeyFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null, MyObj::getText));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_key_function_returns_null() {
-    expectKeyFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null, MyObj::getText, 9));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_fails_if_value_function_returns_null() {
-    expectValueFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(MyObj::getId, s -> null));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_value_function_returns_null() {
-    expectValueFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(MyObj::getId, s -> null, 9));
-  }
-
-  @Test
-  public void uniqueIndex_returns_map() {
-    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId))).containsOnly(entry(1, MY_OBJ_1_A), entry(2, MY_OBJ_2_B), entry(3, MY_OBJ_3_C));
-  }
-
-  @Test
-  public void uniqueIndex_with_expected_size_returns_map() {
-    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId, 3))).containsOnly(entry(1, MY_OBJ_1_A), entry(2, MY_OBJ_2_B), entry(3, MY_OBJ_3_C));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_returns_map() {
-    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId, MyObj::getText))).containsOnly(entry(1, "A"), entry(2, "B"), entry(3, "C"));
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_returns_map() {
-    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId, MyObj::getText, 9))).containsOnly(entry(1, "A"), entry(2, "B"), entry(3, "C"));
-  }
-
-  @Test
-  public void uniqueIndex_parallel_stream() {
-    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity()));
-    assertThat(map.keySet()).isEqualTo(HUGE_SET);
-    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
-  }
-
-  @Test
-  public void uniqueIndex_with_expected_size_parallel_stream() {
-    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity(), HUGE_LIST.size()));
-    assertThat(map.keySet()).isEqualTo(HUGE_SET);
-    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_parallel_stream() {
-    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity(), identity()));
-    assertThat(map.keySet()).isEqualTo(HUGE_SET);
-    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
-  }
-
-  @Test
-  public void uniqueIndex_with_valueFunction_and_expected_size_parallel_stream() {
-    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity(), identity(), HUGE_LIST.size()));
-    assertThat(map.keySet()).isEqualTo(HUGE_SET);
-    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
-  }
-
-  @Test
-  public void index_empty_stream_returns_empty_map() {
-    assertThat(Collections.<MyObj>emptyList().stream().collect(index(MyObj::getId)).size()).isEqualTo(0);
-    assertThat(Collections.<MyObj>emptyList().stream().collect(index(MyObj::getId, MyObj::getText)).size()).isEqualTo(0);
-  }
-
-  @Test
-  public void index_fails_if_key_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't be null");
-
-    index(null);
-  }
-
-  @Test
-  public void index_with_valueFunction_fails_if_key_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't be null");
-
-    index(null, MyObj::getText);
-  }
-
-  @Test
-  public void index_with_valueFunction_fails_if_value_function_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Value function can't be null");
-
-    index(MyObj::getId, null);
-  }
-
-  @Test
-  public void index_fails_if_key_function_returns_null() {
-    expectKeyFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(index(s -> null));
-  }
-
-  @Test
-  public void index_with_valueFunction_fails_if_key_function_returns_null() {
-    expectKeyFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(index(s -> null, MyObj::getText));
-  }
-
-  @Test
-  public void index_with_valueFunction_fails_if_value_function_returns_null() {
-    expectValueFunctionCantReturnNullNPE();
-
-    SINGLE_ELEMENT_LIST.stream().collect(index(MyObj::getId, s -> null));
-  }
-
-  @Test
-  public void index_supports_duplicate_keys() {
-    Multimap<Integer, MyObj> multimap = LIST_WITH_DUPLICATE_ID.stream().collect(index(MyObj::getId));
-
-    assertThat(multimap.keySet()).containsOnly(1, 2);
-    assertThat(multimap.get(1)).containsOnly(MY_OBJ_1_A, MY_OBJ_1_C);
-    assertThat(multimap.get(2)).containsOnly(MY_OBJ_2_B);
-  }
-
-  @Test
-  public void uniqueIndex_supports_duplicate_keys() {
-    Multimap<Integer, String> multimap = LIST_WITH_DUPLICATE_ID.stream().collect(index(MyObj::getId, MyObj::getText));
-
-    assertThat(multimap.keySet()).containsOnly(1, 2);
-    assertThat(multimap.get(1)).containsOnly("A", "C");
-    assertThat(multimap.get(2)).containsOnly("B");
-  }
-
-  @Test
-  public void index_returns_multimap() {
-    Multimap<Integer, MyObj> multimap = LIST.stream().collect(index(MyObj::getId));
-
-    assertThat(multimap.size()).isEqualTo(3);
-    Map<Integer, Collection<MyObj>> map = multimap.asMap();
-    assertThat(map.get(1)).containsOnly(MY_OBJ_1_A);
-    assertThat(map.get(2)).containsOnly(MY_OBJ_2_B);
-    assertThat(map.get(3)).containsOnly(MY_OBJ_3_C);
-  }
-
-  @Test
-  public void index_with_valueFunction_returns_multimap() {
-    Multimap<Integer, String> multimap = LIST.stream().collect(index(MyObj::getId, MyObj::getText));
-
-    assertThat(multimap.size()).isEqualTo(3);
-    Map<Integer, Collection<String>> map = multimap.asMap();
-    assertThat(map.get(1)).containsOnly("A");
-    assertThat(map.get(2)).containsOnly("B");
-    assertThat(map.get(3)).containsOnly("C");
-  }
-
-  @Test
-  public void index_parallel_stream() {
-    Multimap<String, String> multimap = HUGE_LIST.parallelStream().collect(index(identity()));
-
-    assertThat(multimap.keySet()).isEqualTo(HUGE_SET);
-  }
-
-  @Test
-  public void index_with_valueFunction_parallel_stream() {
-    Multimap<String, String> multimap = HUGE_LIST.parallelStream().collect(index(identity(), identity()));
-
-    assertThat(multimap.keySet()).isEqualTo(HUGE_SET);
-  }
-
-  @Test
-  public void join_on_empty_stream_returns_empty_string() {
-    assertThat(Collections.emptyList().stream().collect(join(Joiner.on(",")))).isEmpty();
-  }
-
-  @Test
-  public void join_fails_with_NPE_if_joiner_is_null() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Joiner can't be null");
-
-    join(null);
-  }
-
-  @Test
-  public void join_applies_joiner_to_stream() {
-    assertThat(Arrays.asList("1", "2", "3", "4").stream().collect(join(Joiner.on(","))))
-      .isEqualTo("1,2,3,4");
-  }
-
-  @Test
-  public void join_does_not_support_parallel_stream_and_fails_with_ISE() {
-    Stream<String> hugeStream = HUGE_LIST.parallelStream();
-
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Parallel processing is not supported");
-
-    hugeStream.collect(join(Joiner.on(" ")));
-  }
-
-  @Test
-  public void join_supports_null_if_joiner_does() {
-    Stream<String> stream = Arrays.asList("1", null).stream();
-
-    expectedException.expect(NullPointerException.class);
-
-    stream.collect(join(Joiner.on(",")));
-  }
-
-  private void expectedDuplicateKey1IAE() {
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("Duplicate key 1");
-  }
-
-  private void expectKeyFunctionCantReturnNullNPE() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Key function can't return null");
-  }
-
-  private void expectValueFunctionCantReturnNullNPE() {
-    expectedException.expect(NullPointerException.class);
-    expectedException.expectMessage("Value function can't return null");
-  }
-
-  private static final class MyObj {
-    private final int id;
-    private final String text;
-
-    public MyObj(int id, String text) {
-      this.id = id;
-      this.text = text;
-    }
-
-    public int getId() {
-      return id;
-    }
-
-    public String getText() {
-      return text;
-    }
-  }
-}
diff --git a/sonar-core/src/test/java/org/sonar/core/util/stream/MoreCollectorsTest.java b/sonar-core/src/test/java/org/sonar/core/util/stream/MoreCollectorsTest.java
new file mode 100644 (file)
index 0000000..8a1e1c0
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.core.util.stream;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static java.util.function.Function.identity;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+import static org.sonar.core.util.stream.MoreCollectors.index;
+import static org.sonar.core.util.stream.MoreCollectors.join;
+import static org.sonar.core.util.stream.MoreCollectors.toArrayList;
+import static org.sonar.core.util.stream.MoreCollectors.toHashSet;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
+import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
+
+public class MoreCollectorsTest {
+
+  private static final List<String> HUGE_LIST = IntStream.range(0, 2_000).mapToObj(String::valueOf).collect(java.util.stream.Collectors.toList());
+  private static final Set<String> HUGE_SET = new HashSet<>(HUGE_LIST);
+  private static final MyObj MY_OBJ_1_A = new MyObj(1, "A");
+  private static final MyObj MY_OBJ_1_C = new MyObj(1, "C");
+  private static final MyObj MY_OBJ_2_B = new MyObj(2, "B");
+  private static final MyObj MY_OBJ_3_C = new MyObj(3, "C");
+  private static final List<MyObj> SINGLE_ELEMENT_LIST = Arrays.asList(MY_OBJ_1_A);
+  private static final List<MyObj> LIST_WITH_DUPLICATE_ID = Arrays.asList(MY_OBJ_1_A, MY_OBJ_2_B, MY_OBJ_1_C);
+  private static final List<MyObj> LIST = Arrays.asList(MY_OBJ_1_A, MY_OBJ_2_B, MY_OBJ_3_C);
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void toList_builds_an_ImmutableList() {
+    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toList());
+    assertThat(res).isInstanceOf(ImmutableList.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toList_parallel_stream() {
+    assertThat(HUGE_LIST.parallelStream().collect(toList())).isEqualTo(HUGE_LIST);
+  }
+
+  @Test
+  public void toList_with_size_builds_an_ImmutableList() {
+    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toList(30));
+    assertThat(res).isInstanceOf(ImmutableList.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toList_with_size_parallel_stream() {
+    assertThat(HUGE_LIST.parallelStream().collect(toList(HUGE_LIST.size()))).isEqualTo(HUGE_LIST);
+  }
+
+  @Test
+  public void toSet_builds_an_ImmutableSet() {
+    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toSet());
+    assertThat(res).isInstanceOf(ImmutableSet.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toSet_parallel_stream() {
+    assertThat(HUGE_SET.parallelStream().collect(toSet())).isEqualTo(HUGE_SET);
+  }
+
+  @Test
+  public void toSet_with_size_builds_an_ImmutableSet() {
+    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toSet(30));
+    assertThat(res).isInstanceOf(ImmutableSet.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toSet_with_size_parallel_stream() {
+    assertThat(HUGE_SET.parallelStream().collect(toSet(HUGE_SET.size()))).isEqualTo(HUGE_SET);
+  }
+
+  @Test
+  public void toArrayList_builds_an_ArrayList() {
+    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toArrayList());
+    assertThat(res).isInstanceOf(ArrayList.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toArrayList_parallel_stream() {
+    assertThat(HUGE_LIST.parallelStream().collect(toArrayList())).isEqualTo(HUGE_LIST);
+  }
+
+  @Test
+  public void toArrayList_with_size_builds_an_ArrayList() {
+    List<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toArrayList(30));
+    assertThat(res).isInstanceOf(ArrayList.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toArrayList_with_size_parallel_stream() {
+    assertThat(HUGE_LIST.parallelStream().collect(toArrayList(HUGE_LIST.size()))).isEqualTo(HUGE_LIST);
+  }
+
+  @Test
+  public void toHashSet_builds_an_HashSet() {
+    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toHashSet());
+    assertThat(res).isInstanceOf(HashSet.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toHashSet_parallel_stream() {
+    assertThat(HUGE_SET.parallelStream().collect(toHashSet())).isEqualTo(HUGE_SET);
+  }
+
+  @Test
+  public void toHashSet_with_size_builds_an_ArrayList() {
+    Set<Integer> res = Arrays.asList(1, 2, 3, 4, 5).stream().collect(toHashSet(30));
+    assertThat(res).isInstanceOf(HashSet.class)
+      .containsExactly(1, 2, 3, 4, 5);
+  }
+
+  @Test
+  public void toHashSet_with_size_parallel_stream() {
+    assertThat(HUGE_SET.parallelStream().collect(toHashSet(HUGE_SET.size()))).isEqualTo(HUGE_SET);
+  }
+
+  @Test
+  public void uniqueIndex_empty_stream_returns_empty_map() {
+    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId))).isEmpty();
+    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId, 6))).isEmpty();
+    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId, MyObj::getText))).isEmpty();
+    assertThat(Collections.<MyObj>emptyList().stream().collect(uniqueIndex(MyObj::getId, MyObj::getText, 10))).isEmpty();
+  }
+
+  @Test
+  public void uniqueIndex_fails_when_there_is_duplicate_keys() {
+    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
+
+    expectedDuplicateKey1IAE();
+
+    stream.collect(uniqueIndex(MyObj::getId));
+  }
+
+  @Test
+  public void uniqueIndex_with_expected_size_fails_when_there_is_duplicate_keys() {
+    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
+
+    expectedDuplicateKey1IAE();
+
+    stream.collect(uniqueIndex(MyObj::getId, 1));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_fails_when_there_is_duplicate_keys() {
+    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
+
+    expectedDuplicateKey1IAE();
+
+    stream.collect(uniqueIndex(MyObj::getId, MyObj::getText));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_fails_when_there_is_duplicate_keys() {
+    Stream<MyObj> stream = LIST_WITH_DUPLICATE_ID.stream();
+
+    expectedDuplicateKey1IAE();
+
+    stream.collect(uniqueIndex(MyObj::getId, MyObj::getText, 10));
+  }
+
+  @Test
+  public void uniqueIndex_fails_if_key_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't be null");
+
+    uniqueIndex(null);
+  }
+
+  @Test
+  public void uniqueIndex_with_expected_size_fails_if_key_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't be null");
+
+    uniqueIndex(null, 2);
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_fails_if_key_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't be null");
+
+    uniqueIndex(null, MyObj::getText);
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_key_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't be null");
+
+    uniqueIndex(null, MyObj::getText, 9);
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_fails_if_value_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Value function can't be null");
+
+    uniqueIndex(MyObj::getId, null);
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_value_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Value function can't be null");
+
+    uniqueIndex(MyObj::getId, null, 9);
+  }
+
+  @Test
+  public void uniqueIndex_fails_if_key_function_returns_null() {
+    expectKeyFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null));
+  }
+
+  @Test
+  public void uniqueIndex_with_expected_size_fails_if_key_function_returns_null() {
+    expectKeyFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null, 90));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_fails_if_key_function_returns_null() {
+    expectKeyFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null, MyObj::getText));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_key_function_returns_null() {
+    expectKeyFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(s -> null, MyObj::getText, 9));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_fails_if_value_function_returns_null() {
+    expectValueFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(MyObj::getId, s -> null));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_fails_if_value_function_returns_null() {
+    expectValueFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(uniqueIndex(MyObj::getId, s -> null, 9));
+  }
+
+  @Test
+  public void uniqueIndex_returns_map() {
+    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId))).containsOnly(entry(1, MY_OBJ_1_A), entry(2, MY_OBJ_2_B), entry(3, MY_OBJ_3_C));
+  }
+
+  @Test
+  public void uniqueIndex_with_expected_size_returns_map() {
+    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId, 3))).containsOnly(entry(1, MY_OBJ_1_A), entry(2, MY_OBJ_2_B), entry(3, MY_OBJ_3_C));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_returns_map() {
+    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId, MyObj::getText))).containsOnly(entry(1, "A"), entry(2, "B"), entry(3, "C"));
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_returns_map() {
+    assertThat(LIST.stream().collect(uniqueIndex(MyObj::getId, MyObj::getText, 9))).containsOnly(entry(1, "A"), entry(2, "B"), entry(3, "C"));
+  }
+
+  @Test
+  public void uniqueIndex_parallel_stream() {
+    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity()));
+    assertThat(map.keySet()).isEqualTo(HUGE_SET);
+    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
+  }
+
+  @Test
+  public void uniqueIndex_with_expected_size_parallel_stream() {
+    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity(), HUGE_LIST.size()));
+    assertThat(map.keySet()).isEqualTo(HUGE_SET);
+    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_parallel_stream() {
+    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity(), identity()));
+    assertThat(map.keySet()).isEqualTo(HUGE_SET);
+    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
+  }
+
+  @Test
+  public void uniqueIndex_with_valueFunction_and_expected_size_parallel_stream() {
+    Map<String, String> map = HUGE_LIST.parallelStream().collect(uniqueIndex(identity(), identity(), HUGE_LIST.size()));
+    assertThat(map.keySet()).isEqualTo(HUGE_SET);
+    assertThat(map.values()).containsExactlyElementsOf(HUGE_SET);
+  }
+
+  @Test
+  public void index_empty_stream_returns_empty_map() {
+    assertThat(Collections.<MyObj>emptyList().stream().collect(index(MyObj::getId)).size()).isEqualTo(0);
+    assertThat(Collections.<MyObj>emptyList().stream().collect(index(MyObj::getId, MyObj::getText)).size()).isEqualTo(0);
+  }
+
+  @Test
+  public void index_fails_if_key_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't be null");
+
+    index(null);
+  }
+
+  @Test
+  public void index_with_valueFunction_fails_if_key_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't be null");
+
+    index(null, MyObj::getText);
+  }
+
+  @Test
+  public void index_with_valueFunction_fails_if_value_function_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Value function can't be null");
+
+    index(MyObj::getId, null);
+  }
+
+  @Test
+  public void index_fails_if_key_function_returns_null() {
+    expectKeyFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(index(s -> null));
+  }
+
+  @Test
+  public void index_with_valueFunction_fails_if_key_function_returns_null() {
+    expectKeyFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(index(s -> null, MyObj::getText));
+  }
+
+  @Test
+  public void index_with_valueFunction_fails_if_value_function_returns_null() {
+    expectValueFunctionCantReturnNullNPE();
+
+    SINGLE_ELEMENT_LIST.stream().collect(index(MyObj::getId, s -> null));
+  }
+
+  @Test
+  public void index_supports_duplicate_keys() {
+    Multimap<Integer, MyObj> multimap = LIST_WITH_DUPLICATE_ID.stream().collect(index(MyObj::getId));
+
+    assertThat(multimap.keySet()).containsOnly(1, 2);
+    assertThat(multimap.get(1)).containsOnly(MY_OBJ_1_A, MY_OBJ_1_C);
+    assertThat(multimap.get(2)).containsOnly(MY_OBJ_2_B);
+  }
+
+  @Test
+  public void uniqueIndex_supports_duplicate_keys() {
+    Multimap<Integer, String> multimap = LIST_WITH_DUPLICATE_ID.stream().collect(index(MyObj::getId, MyObj::getText));
+
+    assertThat(multimap.keySet()).containsOnly(1, 2);
+    assertThat(multimap.get(1)).containsOnly("A", "C");
+    assertThat(multimap.get(2)).containsOnly("B");
+  }
+
+  @Test
+  public void index_returns_multimap() {
+    Multimap<Integer, MyObj> multimap = LIST.stream().collect(index(MyObj::getId));
+
+    assertThat(multimap.size()).isEqualTo(3);
+    Map<Integer, Collection<MyObj>> map = multimap.asMap();
+    assertThat(map.get(1)).containsOnly(MY_OBJ_1_A);
+    assertThat(map.get(2)).containsOnly(MY_OBJ_2_B);
+    assertThat(map.get(3)).containsOnly(MY_OBJ_3_C);
+  }
+
+  @Test
+  public void index_with_valueFunction_returns_multimap() {
+    Multimap<Integer, String> multimap = LIST.stream().collect(index(MyObj::getId, MyObj::getText));
+
+    assertThat(multimap.size()).isEqualTo(3);
+    Map<Integer, Collection<String>> map = multimap.asMap();
+    assertThat(map.get(1)).containsOnly("A");
+    assertThat(map.get(2)).containsOnly("B");
+    assertThat(map.get(3)).containsOnly("C");
+  }
+
+  @Test
+  public void index_parallel_stream() {
+    Multimap<String, String> multimap = HUGE_LIST.parallelStream().collect(index(identity()));
+
+    assertThat(multimap.keySet()).isEqualTo(HUGE_SET);
+  }
+
+  @Test
+  public void index_with_valueFunction_parallel_stream() {
+    Multimap<String, String> multimap = HUGE_LIST.parallelStream().collect(index(identity(), identity()));
+
+    assertThat(multimap.keySet()).isEqualTo(HUGE_SET);
+  }
+
+  @Test
+  public void join_on_empty_stream_returns_empty_string() {
+    assertThat(Collections.emptyList().stream().collect(join(Joiner.on(",")))).isEmpty();
+  }
+
+  @Test
+  public void join_fails_with_NPE_if_joiner_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Joiner can't be null");
+
+    join(null);
+  }
+
+  @Test
+  public void join_applies_joiner_to_stream() {
+    assertThat(Arrays.asList("1", "2", "3", "4").stream().collect(join(Joiner.on(","))))
+      .isEqualTo("1,2,3,4");
+  }
+
+  @Test
+  public void join_does_not_support_parallel_stream_and_fails_with_ISE() {
+    Stream<String> hugeStream = HUGE_LIST.parallelStream();
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Parallel processing is not supported");
+
+    hugeStream.collect(join(Joiner.on(" ")));
+  }
+
+  @Test
+  public void join_supports_null_if_joiner_does() {
+    Stream<String> stream = Arrays.asList("1", null).stream();
+
+    expectedException.expect(NullPointerException.class);
+
+    stream.collect(join(Joiner.on(",")));
+  }
+
+  private void expectedDuplicateKey1IAE() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Duplicate key 1");
+  }
+
+  private void expectKeyFunctionCantReturnNullNPE() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Key function can't return null");
+  }
+
+  private void expectValueFunctionCantReturnNullNPE() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("Value function can't return null");
+  }
+
+  private static final class MyObj {
+    private final int id;
+    private final String text;
+
+    public MyObj(int id, String text) {
+      this.id = id;
+      this.text = text;
+    }
+
+    public int getId() {
+      return id;
+    }
+
+    public String getText() {
+      return text;
+    }
+  }
+}
index da5482356f487064aa5a9bfb017e89d0a2fc9224..446fbd4089b5d7cf8f105c26936440fb23936fbe 100644 (file)
@@ -37,7 +37,7 @@ import org.sonar.api.batch.sensor.coverage.NewCoverage;
 import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.core.util.stream.Collectors;
+import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.scanner.scan.measure.MeasureCache;
 import org.sonar.scanner.sensor.coverage.CoverageExclusions;
 
@@ -104,9 +104,9 @@ public final class ZeroCoverageSensor implements Sensor {
 
   private boolean isCoverageMeasuresAlreadyDefined(InputFile f) {
     Set<String> metricKeys = StreamSupport.stream(measureCache.byComponentKey(f.key()).spliterator(), false)
-      .map(new MeasureToMetricKey()).collect(Collectors.toSet());
+      .map(new MeasureToMetricKey()).collect(MoreCollectors.toSet());
     Function<Metric, String> metricToKey = new MetricToKey();
-    Set<String> allCoverageMetricKeys = CoverageType.UNIT.allMetrics().stream().map(metricToKey).collect(Collectors.toSet());
+    Set<String> allCoverageMetricKeys = CoverageType.UNIT.allMetrics().stream().map(metricToKey).collect(MoreCollectors.toSet());
     return !Sets.intersection(metricKeys, allCoverageMetricKeys).isEmpty();
   }