aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-db-dao
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2017-06-12 22:57:00 +0200
committerEric Hartmann <hartmann.eric@gmail.com>2017-06-14 15:43:13 +0200
commitbce59a878501872b105e120bc0d8e13494f79aee (patch)
tree44862b1c6e1887eddd561223ed12b8ffefcd7044 /server/sonar-db-dao
parentdd5713279b5b6beccdb5cc65681dbde25898f035 (diff)
downloadsonarqube-bce59a878501872b105e120bc0d8e13494f79aee.tar.gz
sonarqube-bce59a878501872b105e120bc0d8e13494f79aee.zip
SONAR-9305 Built-in quality profiles should be updated automatically
Diffstat (limited to 'server/sonar-db-dao')
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java15
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java6
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java14
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java6
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml23
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml19
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java57
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java33
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java16
9 files changed, 180 insertions, 9 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java
index 71002640fad..e62d881de6d 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java
@@ -71,6 +71,10 @@ public class ActiveRuleDao implements Dao {
return selectByProfileUuid(dbSession, profile.getKee());
}
+ public List<ActiveRuleDto> selectByRuleProfile(DbSession dbSession, RulesProfileDto ruleProfileDto) {
+ return mapper(dbSession).selectByRuleProfileUuid(ruleProfileDto.getKee());
+ }
+
public ActiveRuleDto insert(DbSession dbSession, ActiveRuleDto item) {
Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED);
Preconditions.checkArgument(item.getRuleId() != null, RULE_IS_NOT_PERSISTED);
@@ -101,6 +105,11 @@ public class ActiveRuleDao implements Dao {
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteByRuleProfileUuids);
}
+ public void deleteByIds(DbSession dbSession, List<Integer> activeRuleIds) {
+ ActiveRuleMapper mapper = mapper(dbSession);
+ DatabaseUtils.executeLargeUpdates(activeRuleIds, mapper::deleteByIds);
+ }
+
public void deleteParametersByRuleProfileUuids(DbSession dbSession, Collection<String> rulesProfileUuids) {
ActiveRuleMapper mapper = mapper(dbSession);
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteParametersByRuleProfileUuids);
@@ -152,6 +161,11 @@ public class ActiveRuleDao implements Dao {
}
}
+ public void deleteParamsByActiveRuleIds(DbSession dbSession, List<Integer> activeRuleIds) {
+ ActiveRuleMapper mapper = mapper(dbSession);
+ DatabaseUtils.executeLargeUpdates(activeRuleIds, mapper::deleteParamsByActiveRuleIds);
+ }
+
/**
* Active rule on removed rule are NOT taken into account
*/
@@ -176,5 +190,4 @@ public class ActiveRuleDao implements Dao {
private static ActiveRuleMapper mapper(DbSession dbSession) {
return dbSession.getMapper(ActiveRuleMapper.class);
}
-
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java
index 9e58d80c3d9..5c384a20ccd 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/ActiveRuleMapper.java
@@ -36,6 +36,8 @@ public interface ActiveRuleMapper {
void deleteByRuleProfileUuids(@Param("rulesProfileUuids") Collection<String> rulesProfileUuids);
+ void deleteByIds(@Param("ids") Collection<Integer> ids);
+
@CheckForNull
ActiveRuleDto selectByKey(@Param("ruleProfileUuid") String ruleProfileUuid, @Param("repository") String repository, @Param("rule") String rule);
@@ -49,6 +51,8 @@ public interface ActiveRuleMapper {
List<OrgActiveRuleDto> selectByProfileUuid(String uuid);
+ List<ActiveRuleDto> selectByRuleProfileUuid(@Param("ruleProfileUuid") String uuid);
+
void insertParameter(ActiveRuleParamDto dto);
void updateParameter(ActiveRuleParamDto dto);
@@ -59,6 +63,8 @@ public interface ActiveRuleMapper {
void deleteParameter(int activeRuleParamId);
+ void deleteParamsByActiveRuleIds(@Param("activeRuleIds") Collection<Integer> activeRuleIds);
+
List<ActiveRuleParamDto> selectParamsByActiveRuleId(int activeRuleId);
List<ActiveRuleParamDto> selectParamsByActiveRuleIds(@Param("ids") List<Integer> ids);
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java
index 14b53010472..6f82c926bd1 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java
@@ -109,9 +109,15 @@ public class QualityProfileDao implements Dao {
}
}
+ public void update(DbSession dbSession, RulesProfileDto rulesProfile) {
+ QualityProfileMapper mapper = mapper(dbSession);
+ long now = system.now();
+ mapper.updateRuleProfile(rulesProfile, new Date(now));
+ }
+
private void doUpdate(QualityProfileMapper mapper, QProfileDto profile, long now) {
- mapper.updateRuleProfile(profile, new Date(now));
- mapper.updateOrgQProfile(profile, now);
+ mapper.updateRuleProfile(RulesProfileDto.from(profile), new Date(now));
+ mapper.updateOrgQProfile(OrgQProfileDto.from(profile), now);
}
public List<QProfileDto> selectDefaultProfiles(DbSession dbSession, OrganizationDto organization, Collection<String> languages) {
@@ -220,6 +226,10 @@ public class QualityProfileDao implements Dao {
DatabaseUtils.executeLargeUpdates(rulesProfileUuids, mapper::deleteRuleProfilesByUuids);
}
+ public List<QProfileDto> selectChildrenOfBuiltInRulesProfile(DbSession dbSession, RulesProfileDto rulesProfile) {
+ return mapper(dbSession).selectChildrenOfBuiltInRulesProfile(rulesProfile.getKee());
+ }
+
private static String sqlQueryString(@Nullable String query) {
if (query == null) {
return "%";
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java
index 9121d9a40b4..758786dc15c 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java
@@ -32,9 +32,9 @@ public interface QualityProfileMapper {
void insertRuleProfile(@Param("dto") RulesProfileDto dto, @Param("now") Date now);
- void updateRuleProfile(@Param("dto") QProfileDto dto, @Param("now") Date now);
+ void updateRuleProfile(@Param("dto") RulesProfileDto dto, @Param("now") Date now);
- void updateOrgQProfile(@Param("dto") QProfileDto dto, @Param("now") long now);
+ void updateOrgQProfile(@Param("dto") OrgQProfileDto dto, @Param("now") long now);
void deleteRuleProfilesByUuids(@Param("uuids") Collection<String> uuids);
@@ -121,4 +121,6 @@ public interface QualityProfileMapper {
List<String> selectUuidsOfCustomRuleProfiles(@Param("language") String language, @Param("name") String name);
void renameRuleProfiles(@Param("newName") String newName, @Param("updatedAt") Date updatedAt, @Param("uuids") Collection<String> uuids);
+
+ List<QProfileDto> selectChildrenOfBuiltInRulesProfile(@Param("rulesProfileUuid") String rulesProfileUuid);
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml
index 9948c028ebe..840467e7e8b 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/ActiveRuleMapper.xml
@@ -81,6 +81,13 @@
)
</delete>
+ <delete id="deleteByIds" parameterType="Integer">
+ delete from active_rules
+ where
+ id in
+ <foreach collection="ids" open="(" close=")" item="id" separator=",">#{id, jdbcType=INTEGER}</foreach>
+ </delete>
+
<select id="selectByKey" parameterType="map" resultType="ActiveRule">
select
<include refid="activeRuleColumns"/>
@@ -116,6 +123,15 @@
where oqp.uuid = #{id, jdbcType=VARCHAR}
</select>
+ <select id="selectByRuleProfileUuid" parameterType="string" resultType="org.sonar.db.qualityprofile.ActiveRuleDto">
+ select
+ <include refid="activeRuleColumns"/>
+ from active_rules a
+ <include refid="activeRuleKeyJoin"/>
+ where
+ rp.kee = #{ruleProfileUuid, jdbcType=VARCHAR}
+ </select>
+
<select id="selectByRuleId" parameterType="map" resultType="org.sonar.db.qualityprofile.OrgActiveRuleDto">
select
<include refid="orgActiveRuleColumns"/>
@@ -203,6 +219,13 @@
DELETE FROM active_rule_parameters WHERE id=#{id, jdbcType=BIGINT}
</delete>
+ <delete id="deleteParamsByActiveRuleIds" parameterType="Integer">
+ delete from active_rule_parameters
+ where
+ active_rule_id in
+ <foreach collection="activeRuleIds" open="(" close=")" item="activeRuleId" separator=",">#{activeRuleId, jdbcType=INTEGER}</foreach>
+ </delete>
+
<select id="selectParamsByActiveRuleId" parameterType="Integer" resultType="ActiveRuleParam">
select
<include refid="activeRuleParamColumns"/>
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml
index 35b8cbdfcb0..1f8add3639b 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml
@@ -77,18 +77,18 @@
rules_updated_at = #{dto.rulesUpdatedAt, jdbcType=VARCHAR},
is_built_in = #{dto.isBuiltIn, jdbcType=BOOLEAN}
where
- kee = #{dto.rulesProfileUuid, jdbcType=VARCHAR}
+ kee = #{dto.kee, jdbcType=VARCHAR}
</update>
<update id="updateOrgQProfile" parameterType="map">
update org_qprofiles
set
- parent_uuid = #{dto.parentKee, jdbcType=VARCHAR},
+ parent_uuid = #{dto.parentUuid, jdbcType=VARCHAR},
last_used = #{dto.lastUsed, jdbcType=BIGINT},
user_updated_at = #{dto.userUpdatedAt, jdbcType=BIGINT},
updated_at = #{now, jdbcType=BIGINT}
where
- uuid = #{dto.kee, jdbcType=VARCHAR}
+ uuid = #{dto.uuid, jdbcType=VARCHAR}
</update>
<delete id="deleteRuleProfilesByUuids" parameterType="String">
@@ -335,5 +335,18 @@
where
kee in <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">#{uuid, jdbcType=VARCHAR}</foreach>
</update>
+
+ <select id="selectChildrenOfBuiltInRulesProfile" parameterType="string" resultType="org.sonar.db.qualityprofile.QProfileDto">
+ select
+ <include refid="qProfileColumns"/>
+ from org_qprofiles oqp
+ inner join rules_profiles rp on oqp.rules_profile_uuid = rp.kee
+ inner join org_qprofiles parentoqp on parentoqp.uuid = oqp.parent_uuid
+ inner join rules_profiles parentrp on parentoqp.rules_profile_uuid = parentrp.kee
+ where
+ parentrp.kee = #{rulesProfileUuid, jdbcType=VARCHAR}
+ and parentrp.is_built_in = ${_true}
+ and oqp.parent_uuid is not null
+ </select>
</mapper>
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java
index fd293237cda..62c4c989d77 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java
@@ -151,7 +151,7 @@ public class ActiveRuleDaoTest {
}
@Test
- public void selectByProfileUuid_ignores_removed_rules() throws Exception {
+ public void selectByProfileUuid_ignores_removed_rules() {
ActiveRuleDto activeRule = createFor(profile1, removedRule).setSeverity(BLOCKER);
underTest.insert(dbSession, activeRule);
@@ -159,6 +159,22 @@ public class ActiveRuleDaoTest {
}
@Test
+ public void selectByRuleProfileUuid() {
+ ActiveRuleDto activeRule1 = createFor(profile1, rule1).setSeverity(BLOCKER);
+ ActiveRuleDto activeRule2 = createFor(profile1, rule2).setSeverity(MAJOR);
+ underTest.insert(dbSession, activeRule1);
+ underTest.insert(dbSession, activeRule2);
+
+ List<ActiveRuleDto> result = underTest.selectByRuleProfile(dbSession, RulesProfileDto.from(profile1));
+ assertThat(result)
+ .hasSize(2)
+ .extracting(ActiveRuleDto::getProfileId, ActiveRuleDto::getRuleKey, ActiveRuleDto::getSeverityString)
+ .containsOnly(tuple(profile1.getId(), rule1.getKey(), BLOCKER), tuple(profile1.getId(), rule2.getKey(), MAJOR));
+
+ assertThat(underTest.selectByProfile(dbSession, profile2)).isEmpty();
+ }
+
+ @Test
public void insert() {
ActiveRuleDto activeRule = createFor(profile1, rule1)
.setSeverity(BLOCKER)
@@ -297,6 +313,29 @@ public class ActiveRuleDaoTest {
assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1);
}
+ @Test
+ public void deleteByIds() {
+ ActiveRuleDto ar1 = underTest.insert(dbSession, newRow(profile1, rule1));
+ ActiveRuleDto ar2 = underTest.insert(dbSession, newRow(profile1, rule2));
+ ActiveRuleDto ar3 = underTest.insert(dbSession, newRow(profile2, rule1));
+
+ underTest.deleteByIds(dbSession, asList(ar1.getId(), ar3.getId()));
+
+ assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1);
+ assertThat(underTest.selectByProfile(dbSession, profile1))
+ .extracting(ActiveRuleDto::getId)
+ .containsExactly(ar2.getId());
+ }
+
+ @Test
+ public void deleteByIds_does_nothing_if_empty_list_of_ids() {
+ underTest.insert(dbSession, newRow(profile1, rule1));
+
+ underTest.deleteByIds(dbSession, emptyList());
+
+ assertThat(db.countRowsOfTable(dbSession, "active_rules")).isEqualTo(1);
+ }
+
private static ActiveRuleDto newRow(QProfileDto profile, RuleDefinitionDto rule) {
return createFor(profile, rule).setSeverity(BLOCKER);
}
@@ -461,6 +500,22 @@ public class ActiveRuleDaoTest {
}
@Test
+ public void deleteParamsByActiveRuleIds() {
+ ActiveRuleDto ar1 = underTest.insert(dbSession, newRow(profile1, rule1));
+ ActiveRuleParamDto param = ActiveRuleParamDto.createFor(rule1Param1).setValue("foo");
+ underTest.insertParam(dbSession, ar1, param);
+
+ ActiveRuleDto ar2 = underTest.insert(dbSession, newRow(profile1, rule2));
+ ActiveRuleParamDto param2 = ActiveRuleParamDto.createFor(rule2Param1).setValue("bar");
+ underTest.insertParam(dbSession, ar2, param2);
+
+ underTest.deleteParamsByActiveRuleIds(dbSession, asList(ar1.getId()));
+
+ assertThat(underTest.selectParamsByActiveRuleId(dbSession, ar1.getId())).hasSize(0);
+ assertThat(underTest.selectParamsByActiveRuleId(dbSession, ar2.getId())).hasSize(1);
+ }
+
+ @Test
public void test_countActiveRulesByProfileKey_for_a_specified_organization() {
db.qualityProfiles().activateRule(profile1, rule1);
db.qualityProfiles().activateRule(profile1, rule2);
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java
index 3fb9e58832a..48ae7bd63ef 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileDaoTest.java
@@ -49,7 +49,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.sonar.core.util.stream.MoreCollectors.toList;
import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto;
+import static org.sonar.db.qualityprofile.RulesProfileDto.from;
public class QualityProfileDaoTest {
@@ -721,4 +723,35 @@ public class QualityProfileDaoTest {
return Arrays.asList(dto1, dto2);
}
+ @Test
+ public void selectChildrenOfBuiltInRulesProfile_must_return_only_inherited_profiles() {
+ OrganizationDto org1 = db.organizations().insert();
+ OrganizationDto org2 = db.organizations().insert();
+ OrganizationDto org3 = db.organizations().insert();
+
+ QProfileDto builtInProfile = db.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(true).setLanguage("java").setName("foo"));
+ QProfileDto javaProfileOrg2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo"));
+ QProfileDto inheritedJavaProfileOrg2 = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(builtInProfile.getKee()));
+ QProfileDto differentLanguage = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("cobol").setName("foo"));
+ QProfileDto differentName = db.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("bar"));
+ QProfileDto javaProfileOrg3 = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo"));
+ QProfileDto inheritedJavaProfileOrg3 = db.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(builtInProfile.getKee()));
+
+ List<QProfileDto> children = db.getDbClient().qualityProfileDao().selectChildrenOfBuiltInRulesProfile(db.getSession(), from(builtInProfile));
+
+ assertThat(children.stream().map(qp -> qp.getId()).collect(toList())).containsExactlyInAnyOrder(
+ inheritedJavaProfileOrg2.getId(), inheritedJavaProfileOrg3.getId());
+ }
+
+ @Test
+ public void selectChildrenOfBuiltInRulesProfile_must_return_empty_list_if_not_built_in() {
+ OrganizationDto org = db.organizations().insert();
+
+ QProfileDto notBuiltInProfile = db.qualityProfiles().insert(org, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo"));
+ QProfileDto inheritedProfile = db.qualityProfiles().insert(org, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo").setParentKee(notBuiltInProfile.getKee()));
+
+ List<QProfileDto> children = db.getDbClient().qualityProfileDao().selectChildrenOfBuiltInRulesProfile(db.getSession(), from(notBuiltInProfile));
+
+ assertThat(children).isEmpty();
+ }
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java
index 10958208dbc..fac9f8c8a33 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualityprofile/QualityProfileTesting.java
@@ -19,8 +19,11 @@
*/
package org.sonar.db.qualityprofile;
+import java.util.function.Consumer;
import org.sonar.core.util.Uuids;
+import static java.util.Arrays.stream;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.apache.commons.lang.math.RandomUtils.nextLong;
@@ -56,4 +59,17 @@ public class QualityProfileTesting {
.setChangeType("ACTIVATED")
.setLogin(randomAlphanumeric(10));
}
+
+ /**
+ * Create an instance of {@link RulesProfileDto} with most of random field values.
+ */
+ public static RulesProfileDto newRuleProfileDto(Consumer<RulesProfileDto>... populators) {
+ RulesProfileDto dto = new RulesProfileDto()
+ .setKee("uuid" + randomAlphabetic(10))
+ .setName("name" + randomAlphabetic(10))
+ .setLanguage("lang" + randomAlphabetic(5))
+ .setIsBuiltIn(false);
+ stream(populators).forEach(p -> p.accept(dto));
+ return dto;
+ }
}