@@ -55,7 +55,8 @@ CREATE TABLE "RULES_PROFILES" ( | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT | |||
"USER_UPDATED_AT" BIGINT, | |||
"IS_BUILT_IN" BOOLEAN NOT NULL | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); | |||
@@ -22,7 +22,6 @@ package org.sonar.db.ce; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.function.Consumer; | |||
import javax.annotation.Nullable; | |||
import org.apache.ibatis.session.RowBounds; | |||
import org.sonar.api.utils.System2; | |||
@@ -93,7 +92,7 @@ public class CeQueueDao implements Dao { | |||
} else { | |||
// executeLargeUpdates won't call the SQL command if knownWorkerUUIDs is empty | |||
executeLargeUpdates(knownWorkerUUIDs, | |||
(Consumer<List<String>>) uuids -> mapper(dbSession).resetTasksWithUnknownWorkerUUIDs(uuids, system2.now()) | |||
uuids -> mapper(dbSession).resetTasksWithUnknownWorkerUUIDs(uuids, system2.now()) | |||
); | |||
} | |||
} |
@@ -38,6 +38,7 @@ import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import static org.sonar.db.DatabaseUtils.executeLargeInputs; | |||
import static org.sonar.db.DatabaseUtils.executeLargeUpdates; | |||
public class QualityProfileDao implements Dao { | |||
@@ -181,6 +182,19 @@ public class QualityProfileDao implements Dao { | |||
return mapper(session).selectProjectAssociations(organization.getUuid(), profileKey, nameQuery); | |||
} | |||
public Collection<String> selectOutdatedProfiles(DbSession dbSession, String language, String name) { | |||
return mapper(dbSession).selectOutdatedProfiles(language, name); | |||
} | |||
public void renameAndCommit(DbSession dbSession, Collection<String> keys, String newName) { | |||
QualityProfileMapper mapper = mapper(dbSession); | |||
Date now = new Date(system.now()); | |||
executeLargeUpdates(keys, partition -> { | |||
mapper.rename(newName, now, partition); | |||
dbSession.commit(); | |||
}); | |||
} | |||
private static String sqlQueryString(@Nullable String query) { | |||
if (query == null) { | |||
return "%"; |
@@ -26,6 +26,9 @@ import org.sonar.core.util.UtcDateUtils; | |||
import org.sonar.db.Dto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
/** | |||
* Represents the table "rules_profiles" | |||
*/ | |||
public class QualityProfileDto extends Dto<String> { | |||
private Integer id; | |||
@@ -43,6 +46,7 @@ public class QualityProfileDto extends Dto<String> { | |||
private Long lastUsed; | |||
private Long userUpdatedAt; | |||
private boolean isDefault; | |||
private boolean isBuiltIn; | |||
public String getOrganizationUuid() { | |||
return organizationUuid; | |||
@@ -151,6 +155,15 @@ public class QualityProfileDto extends Dto<String> { | |||
return this; | |||
} | |||
public boolean isBuiltIn() { | |||
return isBuiltIn; | |||
} | |||
public QualityProfileDto setIsBuiltIn(boolean b) { | |||
this.isBuiltIn = b; | |||
return this; | |||
} | |||
public static QualityProfileDto createFor(String key) { | |||
return new QualityProfileDto().setKee(key); | |||
} |
@@ -20,6 +20,7 @@ | |||
package org.sonar.db.qualityprofile; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
import java.util.List; | |||
import javax.annotation.CheckForNull; | |||
import org.apache.ibatis.annotations.Param; | |||
@@ -87,4 +88,8 @@ public interface QualityProfileMapper { | |||
@Param("organizationUuid") String organizationUuid, | |||
@Param("profileKey") String profileKey, | |||
@Param("nameQuery") String nameQuery); | |||
List<String> selectOutdatedProfiles(@Param("language") String language, @Param("name") String name); | |||
void rename(@Param("newName") String newName, @Param("updatedAt") Date updatedAt, @Param("profileKeys") Collection<String> profileKeys); | |||
} |
@@ -15,11 +15,12 @@ | |||
p.updated_at as updatedAt, | |||
p.rules_updated_at as rulesUpdatedAt, | |||
p.last_used as lastUsed, | |||
p.user_updated_at as userUpdatedAt | |||
p.user_updated_at as userUpdatedAt, | |||
p.is_built_in as isBuiltIn | |||
</sql> | |||
<insert id="insert" parameterType="QualityProfile" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> | |||
INSERT INTO rules_profiles (organization_uuid, kee, parent_kee, name, language, is_default, created_at, updated_at, rules_updated_at, last_used, user_updated_at) | |||
INSERT INTO rules_profiles (organization_uuid, kee, parent_kee, name, language, is_default, created_at, updated_at, rules_updated_at, last_used, user_updated_at, is_built_in) | |||
VALUES ( | |||
#{organizationUuid, jdbcType=VARCHAR}, | |||
#{kee, jdbcType=VARCHAR}, | |||
@@ -31,7 +32,9 @@ | |||
#{updatedAt, jdbcType=TIMESTAMP}, | |||
#{rulesUpdatedAt, jdbcType=VARCHAR}, | |||
#{lastUsed, jdbcType=BIGINT}, | |||
#{userUpdatedAt, jdbcType=BIGINT}) | |||
#{userUpdatedAt, jdbcType=BIGINT}, | |||
#{isBuiltIn, jdbcType=BOOLEAN} | |||
) | |||
</insert> | |||
<update id="update" parameterType="QualityProfile"> | |||
@@ -43,7 +46,8 @@ | |||
updated_at=#{updatedAt, jdbcType=TIMESTAMP}, | |||
rules_updated_at=#{rulesUpdatedAt, jdbcType=VARCHAR}, | |||
last_used=#{lastUsed, jdbcType=BIGINT}, | |||
user_updated_at=#{userUpdatedAt, jdbcType=BIGINT} | |||
user_updated_at=#{userUpdatedAt, jdbcType=BIGINT}, | |||
is_built_in=#{isBuiltIn, jdbcType=BOOLEAN} | |||
WHERE id=#{id} | |||
</update> | |||
@@ -198,15 +202,19 @@ | |||
</select> | |||
<insert id="insertProjectProfileAssociation" keyColumn="id" useGeneratedKeys="true"> | |||
INSERT INTO project_qprofiles (project_uuid, profile_key) VALUES (#{projectUuid}, #{profileKey}) | |||
INSERT INTO project_qprofiles (project_uuid, profile_key) | |||
VALUES (#{projectUuid, jdbcType=VARCHAR}, #{profileKey, jdbcType=VARCHAR}) | |||
</insert> | |||
<update id="updateProjectProfileAssociation"> | |||
UPDATE project_qprofiles SET profile_key=#{profileKey} WHERE project_uuid=#{projectUuid} AND profile_key=#{oldProfileKey} | |||
UPDATE project_qprofiles | |||
SET profile_key=#{profileKey, jdbcType=VARCHAR} | |||
WHERE project_uuid=#{projectUuid, jdbcType=VARCHAR} AND profile_key=#{oldProfileKey, jdbcType=VARCHAR} | |||
</update> | |||
<update id="deleteProjectProfileAssociation"> | |||
DELETE FROM project_qprofiles WHERE project_uuid=#{projectUuid} AND profile_key=#{profileKey} | |||
DELETE FROM project_qprofiles | |||
WHERE project_uuid=#{projectUuid, jdbcType=VARCHAR} AND profile_key=#{profileKey, jdbcType=VARCHAR} | |||
</update> | |||
<update id="deleteProjectAssociationByProfileKeys" parameterType="String"> | |||
@@ -217,5 +225,21 @@ | |||
</foreach> | |||
</update> | |||
<select id="selectOutdatedProfiles" parameterType="map" resultType="string"> | |||
select rp.kee | |||
from rules_profiles rp | |||
inner join organizations o on o.uuid = rp.organization_uuid | |||
where rp.language = #{language, jdbcType=VARCHAR} | |||
and rp.name = #{name, jdbcType=VARCHAR} | |||
and rp.is_built_in = ${_false} | |||
</select> | |||
<update id="rename" parameterType="map"> | |||
update rules_profiles | |||
set | |||
name = #{newName, jdbcType=VARCHAR}, | |||
updated_at = #{updatedAt, jdbcType=TIMESTAMP} | |||
where kee in <foreach collection="profileKeys" open="(" close=")" item="profileKey" separator=",">#{profileKey, jdbcType=VARCHAR}</foreach> | |||
</update> | |||
</mapper> | |||
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.db.qualityprofile; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Map; | |||
@@ -77,7 +78,8 @@ public class QualityProfileDaoTest { | |||
QualityProfileDto dto = QualityProfileDto.createFor("abcde") | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setName("ABCDE") | |||
.setLanguage("xoo"); | |||
.setLanguage("xoo") | |||
.setIsBuiltIn(true); | |||
underTest.insert(dbTester.getSession(), dto); | |||
dbTester.commit(); | |||
@@ -95,7 +97,8 @@ public class QualityProfileDaoTest { | |||
.setName("New Name") | |||
.setLanguage("js") | |||
.setParentKee("fghij") | |||
.setDefault(false); | |||
.setDefault(false) | |||
.setIsBuiltIn(false); | |||
underTest.update(dbSession, dto); | |||
dbSession.commit(); | |||
@@ -168,12 +171,14 @@ public class QualityProfileDaoTest { | |||
assertThat(dto1.getName()).isEqualTo("Sonar Way"); | |||
assertThat(dto1.getLanguage()).isEqualTo("java"); | |||
assertThat(dto1.getParentKee()).isNull(); | |||
assertThat(dto1.isBuiltIn()).isTrue(); | |||
QualityProfileDto dto2 = dtos.get(1); | |||
assertThat(dto2.getId()).isEqualTo(2); | |||
assertThat(dto2.getName()).isEqualTo("Sonar Way"); | |||
assertThat(dto2.getLanguage()).isEqualTo("js"); | |||
assertThat(dto2.getParentKee()).isNull(); | |||
assertThat(dto2.isBuiltIn()).isFalse(); | |||
} | |||
@Test | |||
@@ -451,6 +456,52 @@ public class QualityProfileDaoTest { | |||
assertThat(underTest.selectByProjectAndLanguage(dbSession, project.getKey(), "xoo2").getKey()).isEqualTo(profile2Language2.getKey()); | |||
} | |||
@Test | |||
public void selectOutdatedProfiles_returns_the_custom_profiles_with_specified_name() { | |||
OrganizationDto org1 = dbTester.organizations().insert(); | |||
OrganizationDto org2 = dbTester.organizations().insert(); | |||
OrganizationDto org3 = dbTester.organizations().insert(); | |||
QualityProfileDto outdatedProfile1 = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QualityProfileDto outdatedProfile2 = dbTester.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage("java").setName("foo")); | |||
QualityProfileDto builtInProfile = dbTester.qualityProfiles().insert(org3, p -> p.setIsBuiltIn(true).setLanguage("java").setName("foo")); | |||
QualityProfileDto differentLanguage = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("cobol").setName("foo")); | |||
QualityProfileDto differentName = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage("java").setName("bar")); | |||
Collection<String> keys = underTest.selectOutdatedProfiles(dbSession, "java", "foo"); | |||
assertThat(keys).containsExactlyInAnyOrder(outdatedProfile1.getKee(), outdatedProfile2.getKee()); | |||
} | |||
@Test | |||
public void selectOutdatedProfiles_returns_empty_list_if_no_match() { | |||
assertThat(underTest.selectOutdatedProfiles(dbSession, "java", "foo")).isEmpty(); | |||
} | |||
@Test | |||
public void renameAndCommit_updates_name_of_specified_profiles() { | |||
OrganizationDto org1 = dbTester.organizations().insert(); | |||
OrganizationDto org2 = dbTester.organizations().insert(); | |||
QualityProfileDto fooInOrg1 = dbTester.qualityProfiles().insert(org1, p->p.setName("foo")); | |||
QualityProfileDto fooInOrg2 = dbTester.qualityProfiles().insert(org2, p->p.setName("foo")); | |||
QualityProfileDto bar = dbTester.qualityProfiles().insert(org1, p->p.setName("bar")); | |||
underTest.renameAndCommit(dbSession, asList(fooInOrg1.getKee(), fooInOrg2.getKee()), "foo (copy)"); | |||
assertThat(underTest.selectOrFailByKey(dbSession, fooInOrg1.getKey()).getName()).isEqualTo("foo (copy)"); | |||
assertThat(underTest.selectOrFailByKey(dbSession, fooInOrg2.getKey()).getName()).isEqualTo("foo (copy)"); | |||
assertThat(underTest.selectOrFailByKey(dbSession, bar.getKey()).getName()).isEqualTo("bar"); | |||
} | |||
@Test | |||
public void renameAndCommit_does_nothing_if_empty_keys() { | |||
OrganizationDto org = dbTester.organizations().insert(); | |||
QualityProfileDto profile = dbTester.qualityProfiles().insert(org, p -> p.setName("foo")); | |||
underTest.renameAndCommit(dbSession, Collections.emptyList(), "foo (copy)"); | |||
assertThat(underTest.selectOrFailByKey(dbSession, profile.getKey()).getName()).isEqualTo("foo"); | |||
} | |||
private QualityProfileDto insertQualityProfileDto(String key, String name, String language) { | |||
QualityProfileDto dto = QualityProfileDto.createFor(key) | |||
.setOrganizationUuid(organization.getUuid()) |
@@ -20,6 +20,7 @@ | |||
package org.sonar.db.qualityprofile; | |||
import java.util.Arrays; | |||
import java.util.Optional; | |||
import java.util.function.Consumer; | |||
import org.apache.commons.lang.math.RandomUtils; | |||
import org.sonar.db.DbClient; | |||
@@ -41,6 +42,10 @@ public class QualityProfileDbTester { | |||
this.dbSession = db.getSession(); | |||
} | |||
public Optional<QualityProfileDto> selectByKey(String key) { | |||
return Optional.ofNullable(dbClient.qualityProfileDao().selectByKey(dbSession, key)); | |||
} | |||
/** | |||
* Create a profile with random field values on the specified organization. | |||
*/ |
@@ -1,6 +1,17 @@ | |||
<dataset> | |||
<rules_profiles id="2" name="Sonar Way" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="123456789" user_updated_at="987654321"/> | |||
<rules_profiles id="2" | |||
name="Sonar Way" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="123456789" | |||
user_updated_at="987654321"/> | |||
</dataset> |
@@ -1,23 +1,77 @@ | |||
<dataset> | |||
<rules_profiles id="1" name="Child1" language="java" organization_uuid="org-123" parent_kee="java_parent" kee="java_child1" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="1" | |||
name="Child1" | |||
language="java" | |||
organization_uuid="org-123" | |||
parent_kee="java_parent" | |||
kee="java_child1" | |||
is_default="[false]" | |||
is_built_in="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="2" name="Child2" language="java" organization_uuid="org-123" parent_kee="java_parent" kee="java_child2" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="2" | |||
name="Child2" | |||
language="java" | |||
organization_uuid="org-123" | |||
parent_kee="java_parent" | |||
kee="java_child2" | |||
is_default="[false]" | |||
is_built_in="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="3" name="Parent" language="java" organization_uuid="org-123" parent_kee="[null]" kee="java_parent" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="3" | |||
name="Parent" | |||
language="java" | |||
organization_uuid="org-123" | |||
parent_kee="[null]" | |||
kee="java_parent" | |||
is_default="[false]" | |||
is_built_in="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<!-- Same profile for another language --> | |||
<rules_profiles id="4" name="Child1" language="js" organization_uuid="org-123" parent_kee="js_parent" kee="js_child1" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="4" | |||
name="Child1" | |||
language="js" | |||
organization_uuid="org-123" | |||
parent_kee="js_parent" | |||
kee="js_child1" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="5" name="Child2" language="js" organization_uuid="org-123" parent_kee="js_parent" kee="js_child2" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="5" | |||
name="Child2" | |||
language="js" | |||
organization_uuid="org-123" | |||
parent_kee="js_parent" | |||
kee="js_child2" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="6" name="Parent" language="js" organization_uuid="org-123" parent_kee="[null]" kee="js_parent" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="6" | |||
name="Parent" | |||
language="js" | |||
organization_uuid="org-123" | |||
parent_kee="[null]" | |||
kee="js_parent" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
</dataset> |
@@ -1,13 +1,46 @@ | |||
<dataset> | |||
<rules_profiles id="1" name="Sonar Way" language="java" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="java_sonar_way" is_default="[true]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="[null]" user_updated_at="[null]"/> | |||
<rules_profiles id="1" | |||
name="Sonar Way" | |||
language="java" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="java_sonar_way" | |||
is_built_in="[true]" | |||
is_default="[true]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="[null]" | |||
user_updated_at="[null]"/> | |||
<rules_profiles id="2" name="Sonar Way" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="123456789" user_updated_at="987654321"/> | |||
<rules_profiles id="2" | |||
name="Sonar Way" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="123456789" | |||
user_updated_at="987654321"/> | |||
<rules_profiles id="3" name="ABCDE" language="xoo" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="abcde" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="[null]" user_updated_at="[null]"/> | |||
<rules_profiles id="3" | |||
name="ABCDE" | |||
language="xoo" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="abcde" | |||
is_built_in="[true]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="[null]" | |||
user_updated_at="[null]"/> | |||
</dataset> |
@@ -6,6 +6,7 @@ | |||
organization_uuid="org1" | |||
parent_kee="[null]" | |||
kee="java_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[true]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
@@ -16,6 +17,7 @@ | |||
organization_uuid="org1" | |||
parent_kee="[null]" | |||
kee="js_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[true]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" |
@@ -1,13 +1,40 @@ | |||
<dataset> | |||
<rules_profiles id="3" name="Third" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_third" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="3" | |||
name="Third" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_third" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="1" name="First" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_first" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="1" | |||
name="First" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_first" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="2" name="Second" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_second" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="2" | |||
name="Second" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_second" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
</dataset> |
@@ -1,14 +1,39 @@ | |||
<dataset> | |||
<rules_profiles id="1" name="Sonar Way 1" language="java" organization_uuid="org-123" parent_kee="[null]" kee="java_sonar_way" | |||
<rules_profiles id="1" | |||
name="Sonar Way 1" | |||
language="java" | |||
organization_uuid="org-123" | |||
parent_kee="[null]" | |||
kee="java_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="2" name="Sonar Way" language="js" organization_uuid="org-123" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
<rules_profiles id="2" | |||
name="Sonar Way" | |||
language="js" | |||
organization_uuid="org-123" | |||
parent_kee="[null]" | |||
kee="js_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
<rules_profiles id="3" name="Sonar Way 2" language="java" organization_uuid="org-123" parent_kee="[null]" kee="java_sonar_way2" | |||
<rules_profiles id="3" | |||
name="Sonar Way 2" | |||
language="java" | |||
organization_uuid="org-123" | |||
parent_kee="[null]" | |||
kee="java_sonar_way2" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]"/> | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]"/> | |||
</dataset> |
@@ -1,9 +1,31 @@ | |||
<dataset> | |||
<rules_profiles id="1" name="Sonar Way" language="java" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="java_sonar_way" is_default="[true]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="[null]" user_updated_at="[null]"/> | |||
<rules_profiles id="1" | |||
name="Sonar Way" | |||
language="java" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="java_sonar_way" | |||
is_built_in="[true]" | |||
is_default="[true]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="[null]" | |||
user_updated_at="[null]"/> | |||
<rules_profiles id="2" name="Sonar Way" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="123456789" user_updated_at="987654321"/> | |||
<rules_profiles id="2" | |||
name="Sonar Way" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="123456789" | |||
user_updated_at="987654321"/> | |||
</dataset> |
@@ -1,8 +1,30 @@ | |||
<dataset> | |||
<rules_profiles id="1" name="New Name" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="fghij" kee="java_sonar_way" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="[null]" user_updated_at="[null]"/> | |||
<rules_profiles id="1" | |||
name="New Name" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="fghij" | |||
kee="java_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="[null]" | |||
user_updated_at="[null]"/> | |||
<rules_profiles id="2" name="Sonar Way" language="js" organization_uuid="QualityProfileDaoTest-ORG" parent_kee="[null]" kee="js_sonar_way" is_default="[false]" | |||
rules_updated_at="[null]" created_at="[null]" updated_at="[null]" last_used="123456789" user_updated_at="987654321"/> | |||
<rules_profiles id="2" | |||
name="Sonar Way" | |||
language="js" | |||
organization_uuid="QualityProfileDaoTest-ORG" | |||
parent_kee="[null]" | |||
kee="js_sonar_way" | |||
is_built_in="[false]" | |||
is_default="[false]" | |||
rules_updated_at="[null]" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
last_used="123456789" | |||
user_updated_at="987654321"/> | |||
</dataset> |
@@ -0,0 +1,45 @@ | |||
/* | |||
* 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.server.platform.db.migration.version.v65; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.BooleanColumnDef.newBooleanColumnDefBuilder; | |||
public class AddBuiltInFlagToRulesProfiles extends DdlChange { | |||
public AddBuiltInFlagToRulesProfiles(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new AddColumnsBuilder(getDialect(), "rules_profiles") | |||
.addColumn(newBooleanColumnDefBuilder() | |||
.setColumnName("is_built_in") | |||
.setIsNullable(true) | |||
.build()) | |||
.build()); | |||
} | |||
} |
@@ -41,6 +41,9 @@ public class DbVersion65 implements DbVersion { | |||
.add(1711, "Drop index MANUAL_MEASURES.COMPONENT_UUID", DropIndexManualMeasuresComponentUuid.class) | |||
.add(1712, "Make MANUAL_MEASURES.COMPONENT_UUID not nullable", MakeManualMeasuresComponentUuidNotNullable.class) | |||
.add(1713, "Recreate index MANUAL_MEASURES.COMPONENT_UUID", RecreateIndexManualMeasuresComponentUuid.class) | |||
.add(1714, "Purge developer data", PurgeDeveloperData.class); | |||
.add(1714, "Purge developer data", PurgeDeveloperData.class) | |||
.add(1715, "Add rules_profiles.is_built_in", AddBuiltInFlagToRulesProfiles.class) | |||
.add(1716, "Set rules_profiles.is_built_in to false", SetRulesProfilesIsBuiltInToFalse.class) | |||
.add(1717, "Make rules_profiles.is_built_in not null", MakeRulesProfilesIsBuiltInNotNullable.class); | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* | |||
* 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.server.platform.db.migration.version.v65; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.def.BooleanColumnDef; | |||
import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.BooleanColumnDef.newBooleanColumnDefBuilder; | |||
public class MakeRulesProfilesIsBuiltInNotNullable extends DdlChange { | |||
public MakeRulesProfilesIsBuiltInNotNullable(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
BooleanColumnDef column = newBooleanColumnDefBuilder() | |||
.setColumnName("is_built_in") | |||
.setIsNullable(false) | |||
.build(); | |||
context.execute(new AlterColumnsBuilder(getDialect(), "rules_profiles") | |||
.updateColumn(column) | |||
.build()); | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* 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.server.platform.db.migration.version.v65; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.step.DataChange; | |||
import org.sonar.server.platform.db.migration.step.MassUpdate; | |||
public class SetRulesProfilesIsBuiltInToFalse extends DataChange { | |||
public SetRulesProfilesIsBuiltInToFalse(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select id from rules_profiles where is_built_in is null"); | |||
massUpdate.rowPluralName("rules_profiles"); | |||
massUpdate.update("update rules_profiles set is_built_in=? where id=?"); | |||
massUpdate.execute((row, update) -> { | |||
update.setBoolean(1, false); | |||
update.setLong(2, row.getLong(1)); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -17,7 +17,6 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
package org.sonar.server.platform.db.migration.version.v65; | |||
@@ -0,0 +1,56 @@ | |||
/* | |||
* 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.server.platform.db.migration.version.v65; | |||
import java.sql.SQLException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.db.CoreDbTester; | |||
import static java.sql.Types.BOOLEAN; | |||
public class AddBuiltInFlagToRulesProfilesTest { | |||
@Rule | |||
public final CoreDbTester dbTester = CoreDbTester.createForSchema(AddBuiltInFlagToRulesProfilesTest.class, "rules_profiles_6_4.sql"); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private AddBuiltInFlagToRulesProfiles underTest = new AddBuiltInFlagToRulesProfiles(dbTester.database()); | |||
@Test | |||
public void column_is_added_to_table() throws SQLException { | |||
underTest.execute(); | |||
dbTester.assertColumnDefinition("rules_profiles", "is_built_in", BOOLEAN, null, true); | |||
} | |||
@Test | |||
public void migration_is_not_reentrant() throws SQLException { | |||
underTest.execute(); | |||
expectedException.expect(IllegalStateException.class); | |||
underTest.execute(); | |||
} | |||
} |
@@ -29,12 +29,12 @@ public class DbVersion65Test { | |||
private DbVersion65 underTest = new DbVersion65(); | |||
@Test | |||
public void migrationNumber_starts_at_1600() { | |||
public void migrationNumber_starts_at_1700() { | |||
verifyMinimumMigrationNumber(underTest, 1700); | |||
} | |||
@Test | |||
public void verify_migration_count() { | |||
verifyMigrationCount(underTest, 15); | |||
verifyMigrationCount(underTest, 18); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
/* | |||
* 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.server.platform.db.migration.version.v65; | |||
import java.sql.SQLException; | |||
import java.sql.Types; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.db.CoreDbTester; | |||
public class MakeRulesProfilesIsBuiltInNotNullableTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(MakeRulesProfilesIsBuiltInNotNullableTest.class, "initial.sql"); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private MakeRulesProfilesIsBuiltInNotNullable underTest = new MakeRulesProfilesIsBuiltInNotNullable(db.database()); | |||
@Test | |||
public void execute_makes_column_not_null() throws SQLException { | |||
db.assertColumnDefinition("rules_profiles", "is_built_in", Types.BOOLEAN, null, true); | |||
insertRow(1); | |||
insertRow(2); | |||
underTest.execute(); | |||
db.assertColumnDefinition("rules_profiles", "is_built_in", Types.BOOLEAN, null, false); | |||
} | |||
private void insertRow(int id) { | |||
db.executeInsert( | |||
"RULES_PROFILES", | |||
"NAME", "name_" + id, | |||
"ORGANIZATION_UUID", "org_" + id, | |||
"KEE", "kee" + id, | |||
"IS_DEFAULT", false, | |||
"IS_BUILT_IN", false); | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
/* | |||
* 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.server.platform.db.migration.version.v65; | |||
import java.sql.SQLException; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.db.CoreDbTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class SetRulesProfilesIsBuiltInToFalseTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(SetRulesProfilesIsBuiltInToFalseTest.class, "initial.sql"); | |||
private SetRulesProfilesIsBuiltInToFalse underTest = new SetRulesProfilesIsBuiltInToFalse(db.database()); | |||
@Test | |||
public void has_no_effect_if_table_RULES_PROFILES_is_empty() throws SQLException { | |||
underTest.execute(); | |||
assertThat(db.countRowsOfTable("rules_profiles")).isEqualTo(0); | |||
} | |||
@Test | |||
public void updates_rows_with_null_is_build_in_column_to_false() throws SQLException { | |||
insertRow(1, null); | |||
insertRow(2, null); | |||
assertThat(countRowsWitValue(null)).isEqualTo(2); | |||
assertThat(countRowsWitValue(false)).isEqualTo(0); | |||
underTest.execute(); | |||
assertThat(countRowsWitValue(null)).isEqualTo(0); | |||
assertThat(countRowsWitValue(false)).isEqualTo(2); | |||
} | |||
@Test | |||
public void support_large_number_of_rows() throws SQLException { | |||
for (int i = 0; i < 2_000; i++) { | |||
insertRow(i, null); | |||
} | |||
underTest.execute(); | |||
assertThat(countRowsWitValue(null)).isEqualTo(0); | |||
assertThat(countRowsWitValue(false)).isEqualTo(2_000); | |||
} | |||
@Test | |||
public void execute_is_reentreant() throws SQLException { | |||
insertRow(1, null); | |||
insertRow(2, false); | |||
underTest.execute(); | |||
underTest.execute(); | |||
assertThat(countRowsWitValue(null)).isEqualTo(0); | |||
assertThat(countRowsWitValue(false)).isEqualTo(2); | |||
} | |||
private int countRowsWitValue(@Nullable Boolean value) { | |||
if (value == null) { | |||
return db.countSql("select count(1) from rules_profiles where is_built_in is null"); | |||
} | |||
return db.countSql("select count(1) from rules_profiles where is_built_in=" + value); | |||
} | |||
private void insertRow(int id, @Nullable Boolean builtIn) { | |||
db.executeInsert( | |||
"RULES_PROFILES", | |||
"NAME", "name_" + id, | |||
"ORGANIZATION_UUID", "org_" + id, | |||
"KEE", "kee" + id, | |||
"IS_DEFAULT", false, | |||
"IS_BUILT_IN", builtIn == null ? null : builtIn.toString()); | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"LANGUAGE" VARCHAR(20), | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"KEE" VARCHAR(255) NOT NULL, | |||
"PARENT_KEE" VARCHAR(255), | |||
"RULES_UPDATED_AT" VARCHAR(100), | |||
"IS_DEFAULT" BOOLEAN NOT NULL DEFAULT FALSE, | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); |
@@ -0,0 +1,16 @@ | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"LANGUAGE" VARCHAR(20), | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"KEE" VARCHAR(255) NOT NULL, | |||
"PARENT_KEE" VARCHAR(255), | |||
"RULES_UPDATED_AT" VARCHAR(100), | |||
"IS_DEFAULT" BOOLEAN NOT NULL DEFAULT FALSE, | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT, | |||
"IS_BUILT_IN" BOOLEAN | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); |
@@ -0,0 +1,16 @@ | |||
CREATE TABLE "RULES_PROFILES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"NAME" VARCHAR(100) NOT NULL, | |||
"LANGUAGE" VARCHAR(20), | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"KEE" VARCHAR(255) NOT NULL, | |||
"PARENT_KEE" VARCHAR(255), | |||
"RULES_UPDATED_AT" VARCHAR(100), | |||
"IS_DEFAULT" BOOLEAN NOT NULL DEFAULT FALSE, | |||
"CREATED_AT" TIMESTAMP, | |||
"UPDATED_AT" TIMESTAMP, | |||
"LAST_USED" BIGINT, | |||
"USER_UPDATED_AT" BIGINT, | |||
"IS_BUILT_IN" BOOLEAN | |||
); | |||
CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE"); |
@@ -42,9 +42,9 @@ import org.sonar.db.permission.template.PermissionTemplateDto; | |||
import org.sonar.db.user.GroupDto; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.db.user.UserGroupDto; | |||
import org.sonar.server.qualityprofile.DefinedQProfile; | |||
import org.sonar.server.qualityprofile.DefinedQProfileInsert; | |||
import org.sonar.server.qualityprofile.DefinedQProfileRepository; | |||
import org.sonar.server.qualityprofile.BuiltInQProfile; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsert; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileRepository; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.user.index.UserIndexer; | |||
import org.sonar.server.usergroups.DefaultGroupCreator; | |||
@@ -67,15 +67,15 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
private final UuidFactory uuidFactory; | |||
private final OrganizationValidation organizationValidation; | |||
private final Settings settings; | |||
private final DefinedQProfileRepository definedQProfileRepository; | |||
private final DefinedQProfileInsert definedQProfileInsert; | |||
private final BuiltInQProfileRepository builtInQProfileRepository; | |||
private final BuiltInQProfileInsert builtInQProfileInsert; | |||
private final DefaultGroupCreator defaultGroupCreator; | |||
private final UserIndexer userIndexer; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
public OrganizationCreationImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, | |||
OrganizationValidation organizationValidation, Settings settings, UserIndexer userIndexer, | |||
DefinedQProfileRepository definedQProfileRepository, DefinedQProfileInsert definedQProfileInsert, | |||
BuiltInQProfileRepository builtInQProfileRepository, BuiltInQProfileInsert builtInQProfileInsert, | |||
DefaultGroupCreator defaultGroupCreator, ActiveRuleIndexer activeRuleIndexer) { | |||
this.dbClient = dbClient; | |||
this.system2 = system2; | |||
@@ -83,8 +83,8 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
this.organizationValidation = organizationValidation; | |||
this.settings = settings; | |||
this.userIndexer = userIndexer; | |||
this.definedQProfileRepository = definedQProfileRepository; | |||
this.definedQProfileInsert = definedQProfileInsert; | |||
this.builtInQProfileRepository = builtInQProfileRepository; | |||
this.builtInQProfileInsert = builtInQProfileInsert; | |||
this.defaultGroupCreator = defaultGroupCreator; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
@@ -268,16 +268,16 @@ public class OrganizationCreationImpl implements OrganizationCreation { | |||
} | |||
private void insertQualityProfiles(DbSession dbSession, DbSession batchDbSession, OrganizationDto organization) { | |||
definedQProfileRepository.getQProfilesByLanguage().entrySet() | |||
builtInQProfileRepository.getQProfilesByLanguage().entrySet() | |||
.stream() | |||
.flatMap(entry -> entry.getValue().stream()) | |||
.forEach(profile -> insertQualityProfile(dbSession, batchDbSession, profile, organization)); | |||
} | |||
private void insertQualityProfile(DbSession regularSession, DbSession batchDbSession, DefinedQProfile profile, OrganizationDto organization) { | |||
private void insertQualityProfile(DbSession regularSession, DbSession batchDbSession, BuiltInQProfile profile, OrganizationDto organization) { | |||
LOGGER.debug("Creating quality profile {} for language {} for organization {}", profile.getName(), profile.getLanguage(), organization.getKey()); | |||
definedQProfileInsert.create(regularSession, batchDbSession, profile, organization); | |||
builtInQProfileInsert.create(regularSession, batchDbSession, profile, organization); | |||
} | |||
/** |
@@ -141,9 +141,9 @@ import org.sonar.server.projecttag.ws.ProjectTagsWsModule; | |||
import org.sonar.server.property.InternalPropertiesImpl; | |||
import org.sonar.server.property.ws.PropertiesWs; | |||
import org.sonar.server.qualitygate.QualityGateModule; | |||
import org.sonar.server.qualityprofile.DefinedQProfileCreationImpl; | |||
import org.sonar.server.qualityprofile.DefinedQProfileInsertImpl; | |||
import org.sonar.server.qualityprofile.DefinedQProfileRepositoryImpl; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileCreationImpl; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsertImpl; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryImpl; | |||
import org.sonar.server.qualityprofile.QProfileBackuperImpl; | |||
import org.sonar.server.qualityprofile.QProfileComparison; | |||
import org.sonar.server.qualityprofile.QProfileCopier; | |||
@@ -260,8 +260,8 @@ public class PlatformLevel4 extends PlatformLevel { | |||
BillingValidationsProxyImpl.class, | |||
// quality profile | |||
DefinedQProfileRepositoryImpl.class, | |||
DefinedQProfileInsertImpl.class, | |||
BuiltInQProfileRepositoryImpl.class, | |||
BuiltInQProfileInsertImpl.class, | |||
ActiveRuleIndexer.class, | |||
XMLProfileParser.class, | |||
XMLProfileSerializer.class, | |||
@@ -278,7 +278,7 @@ public class PlatformLevel4 extends PlatformLevel { | |||
QProfileCopier.class, | |||
QProfileBackuperImpl.class, | |||
QProfileResetImpl.class, | |||
DefinedQProfileCreationImpl.class, | |||
BuiltInQProfileCreationImpl.class, | |||
QProfilesWsModule.class, | |||
// rule |
@@ -25,10 +25,10 @@ import org.sonar.server.organization.DefaultOrganizationEnforcer; | |||
import org.sonar.server.platform.ServerLifecycleNotifier; | |||
import org.sonar.server.platform.web.RegisterServletFilters; | |||
import org.sonar.server.qualitygate.RegisterQualityGates; | |||
import org.sonar.server.qualityprofile.CachingDefinedQProfileCreationImpl; | |||
import org.sonar.server.qualityprofile.CachingBuiltInQProfileCreationImpl; | |||
import org.sonar.server.qualityprofile.CachingRuleActivator; | |||
import org.sonar.server.qualityprofile.CachingRuleActivatorContextFactory; | |||
import org.sonar.server.qualityprofile.DefinedQProfileLoader; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileLoader; | |||
import org.sonar.server.qualityprofile.MassRegisterQualityProfiles; | |||
import org.sonar.server.qualityprofile.RegisterQualityProfiles; | |||
import org.sonar.server.rule.RegisterRules; | |||
@@ -58,12 +58,12 @@ public class PlatformLevelStartup extends PlatformLevel { | |||
RegisterMetrics.class, | |||
RegisterQualityGates.class, | |||
RegisterRules.class); | |||
add(DefinedQProfileLoader.class); | |||
add(BuiltInQProfileLoader.class); | |||
addIfStartupLeader( | |||
MassRegisterQualityProfiles.class, | |||
CachingRuleActivatorContextFactory.class, | |||
CachingRuleActivator.class, | |||
CachingDefinedQProfileCreationImpl.class, | |||
CachingBuiltInQProfileCreationImpl.class, | |||
RegisterQualityProfiles.class, | |||
RegisterPermissionTemplates.class, | |||
RenameDeprecatedPropertyKeys.class, |
@@ -38,14 +38,14 @@ import static org.sonar.db.loadedtemplate.LoadedTemplateDto.QUALITY_PROFILE_TYPE | |||
* Represent a Quality Profile as computed from {@link ProfileDefinition} provided by installed plugins. | |||
*/ | |||
@Immutable | |||
public final class DefinedQProfile { | |||
public final class BuiltInQProfile { | |||
private final QProfileName qProfileName; | |||
private final boolean isDefault; | |||
private final String loadedTemplateType; | |||
private final List<org.sonar.api.rules.ActiveRule> activeRules; | |||
private final QProfileName parentQProfileName; | |||
private DefinedQProfile(Builder builder, MessageDigest messageDigest) { | |||
private BuiltInQProfile(Builder builder, MessageDigest messageDigest) { | |||
this.qProfileName = new QProfileName(builder.language, builder.getName()); | |||
this.isDefault = builder.declaredDefault || builder.computedDefault; | |||
this.loadedTemplateType = computeLoadedTemplateType(this.qProfileName, messageDigest); | |||
@@ -138,8 +138,8 @@ public final class DefinedQProfile { | |||
return parentName; | |||
} | |||
DefinedQProfile build(MessageDigest messageDigest) { | |||
return new DefinedQProfile(this, messageDigest); | |||
BuiltInQProfile build(MessageDigest messageDigest) { | |||
return new BuiltInQProfile(this, messageDigest); | |||
} | |||
} | |||
} |
@@ -23,12 +23,12 @@ import java.util.List; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
public interface DefinedQProfileCreation { | |||
public interface BuiltInQProfileCreation { | |||
/** | |||
* Persists the specified {@link DefinedQProfile} of the specified organization and adds any {@link ActiveRuleChange} | |||
* Persists the specified {@link BuiltInQProfile} of the specified organization and adds any {@link ActiveRuleChange} | |||
* to the specified list. | |||
* | |||
* The session is not commit. | |||
*/ | |||
void create(DbSession session, DefinedQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes); | |||
void create(DbSession session, BuiltInQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes); | |||
} |
@@ -28,22 +28,22 @@ import org.sonar.db.loadedtemplate.LoadedTemplateDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
public class DefinedQProfileCreationImpl implements DefinedQProfileCreation { | |||
public class BuiltInQProfileCreationImpl implements BuiltInQProfileCreation { | |||
private final DbClient dbClient; | |||
private final QProfileFactory profileFactory; | |||
private final RuleActivator ruleActivator; | |||
public DefinedQProfileCreationImpl(DbClient dbClient, QProfileFactory profileFactory, RuleActivator ruleActivator) { | |||
public BuiltInQProfileCreationImpl(DbClient dbClient, QProfileFactory profileFactory, RuleActivator ruleActivator) { | |||
this.dbClient = dbClient; | |||
this.profileFactory = profileFactory; | |||
this.ruleActivator = ruleActivator; | |||
} | |||
@Override | |||
public void create(DbSession session, DefinedQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
public void create(DbSession session, BuiltInQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
QualityProfileDto profileDto = dbClient.qualityProfileDao().selectByNameAndLanguage(organization, qualityProfile.getName(), qualityProfile.getLanguage(), session); | |||
if (profileDto == null) { | |||
profileDto = profileFactory.create(session, organization, qualityProfile.getQProfileName(), qualityProfile.isDefault()); | |||
profileDto = profileFactory.createBuiltIn(session, organization, qualityProfile.getQProfileName(), qualityProfile.isDefault()); | |||
for (org.sonar.api.rules.ActiveRule activeRule : qualityProfile.getActiveRules()) { | |||
RuleKey ruleKey = RuleKey.of(activeRule.getRepositoryKey(), activeRule.getRuleKey()); | |||
RuleActivation activation = new RuleActivation(ruleKey); |
@@ -22,6 +22,6 @@ package org.sonar.server.qualityprofile; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
public interface DefinedQProfileInsert { | |||
void create(DbSession session, DbSession batchSession, DefinedQProfile definedQProfile, OrganizationDto organization); | |||
public interface BuiltInQProfileInsert { | |||
void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile, OrganizationDto organization); | |||
} |
@@ -57,14 +57,14 @@ import static com.google.common.base.Preconditions.checkArgument; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
import static java.util.Objects.requireNonNull; | |||
public class DefinedQProfileInsertImpl implements DefinedQProfileInsert { | |||
public class BuiltInQProfileInsertImpl implements BuiltInQProfileInsert { | |||
private final DbClient dbClient; | |||
private final System2 system2; | |||
private final UuidFactory uuidFactory; | |||
private final TypeValidations typeValidations; | |||
private RuleRepository ruleRepository; | |||
public DefinedQProfileInsertImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, TypeValidations typeValidations) { | |||
public BuiltInQProfileInsertImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, TypeValidations typeValidations) { | |||
this.dbClient = dbClient; | |||
this.system2 = system2; | |||
this.uuidFactory = uuidFactory; | |||
@@ -72,22 +72,22 @@ public class DefinedQProfileInsertImpl implements DefinedQProfileInsert { | |||
} | |||
@Override | |||
public void create(DbSession session, DbSession batchSession, DefinedQProfile definedQProfile, OrganizationDto organization) { | |||
public void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile, OrganizationDto organization) { | |||
initRuleRepository(batchSession); | |||
checkArgument(definedQProfile.getParentQProfileName() == null, "Inheritance of Quality Profiles is not supported yet"); | |||
checkArgument(builtInQProfile.getParentQProfileName() == null, "Inheritance of Quality Profiles is not supported yet"); | |||
Date now = new Date(system2.now()); | |||
QualityProfileDto profileDto = insertQualityProfile(session, definedQProfile, organization, now); | |||
QualityProfileDto profileDto = insertQualityProfile(session, builtInQProfile, organization, now); | |||
List<ActiveRuleChange> localChanges = definedQProfile.getActiveRules() | |||
List<ActiveRuleChange> localChanges = builtInQProfile.getActiveRules() | |||
.stream() | |||
.map(activeRule -> insertActiveRule(session, profileDto, activeRule, now.getTime())) | |||
.collect(MoreCollectors.toList()); | |||
localChanges.forEach(change -> dbClient.qProfileChangeDao().insert(batchSession, change.toDto(null))); | |||
insertTemplate(session, definedQProfile, organization); | |||
insertTemplate(session, builtInQProfile, organization); | |||
} | |||
private void initRuleRepository(DbSession session) { | |||
@@ -96,12 +96,13 @@ public class DefinedQProfileInsertImpl implements DefinedQProfileInsert { | |||
} | |||
} | |||
private QualityProfileDto insertQualityProfile(DbSession session, DefinedQProfile definedQProfile, OrganizationDto organization, Date now) { | |||
private QualityProfileDto insertQualityProfile(DbSession session, BuiltInQProfile builtInQProfile, OrganizationDto organization, Date now) { | |||
QualityProfileDto profileDto = QualityProfileDto.createFor(uuidFactory.create()) | |||
.setName(definedQProfile.getName()) | |||
.setName(builtInQProfile.getName()) | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setLanguage(definedQProfile.getLanguage()) | |||
.setDefault(definedQProfile.isDefault()) | |||
.setLanguage(builtInQProfile.getLanguage()) | |||
.setDefault(builtInQProfile.isDefault()) | |||
.setIsBuiltIn(true) | |||
.setRulesUpdatedAtAsDate(now); | |||
dbClient.qualityProfileDao().insert(session, profileDto); | |||
return profileDto; | |||
@@ -163,7 +164,7 @@ public class DefinedQProfileInsertImpl implements DefinedQProfileInsert { | |||
return value; | |||
} | |||
private void insertTemplate(DbSession session, DefinedQProfile qualityProfile, OrganizationDto organization) { | |||
private void insertTemplate(DbSession session, BuiltInQProfile qualityProfile, OrganizationDto organization) { | |||
LoadedTemplateDto template = new LoadedTemplateDto(organization.getUuid(), qualityProfile.getLoadedTemplateType()); | |||
dbClient.loadedTemplateDao().insert(template, session); | |||
} |
@@ -23,18 +23,18 @@ import org.picocontainer.Startable; | |||
/** | |||
* Startable added to {@link org.sonar.server.platform.platformlevel.PlatformLevelStartup} responsible for initializing | |||
* {@link DefinedQProfileRepository}. | |||
* {@link BuiltInQProfileRepository}. | |||
*/ | |||
public class DefinedQProfileLoader implements Startable { | |||
private final DefinedQProfileRepository definedQProfileRepository; | |||
public class BuiltInQProfileLoader implements Startable { | |||
private final BuiltInQProfileRepository builtInQProfileRepository; | |||
public DefinedQProfileLoader(DefinedQProfileRepository definedQProfileRepository) { | |||
this.definedQProfileRepository = definedQProfileRepository; | |||
public BuiltInQProfileLoader(BuiltInQProfileRepository builtInQProfileRepository) { | |||
this.builtInQProfileRepository = builtInQProfileRepository; | |||
} | |||
@Override | |||
public void start() { | |||
definedQProfileRepository.initialize(); | |||
builtInQProfileRepository.initialize(); | |||
} | |||
@Override |
@@ -22,7 +22,7 @@ package org.sonar.server.qualityprofile; | |||
import java.util.List; | |||
import java.util.Map; | |||
public interface DefinedQProfileRepository { | |||
public interface BuiltInQProfileRepository { | |||
/** | |||
* Initializes the Repository. | |||
* | |||
@@ -38,5 +38,5 @@ public interface DefinedQProfileRepository { | |||
* | |||
* @throws IllegalStateException if {@link #initialize()} has not been called | |||
*/ | |||
Map<String, List<DefinedQProfile>> getQProfilesByLanguage(); | |||
Map<String, List<BuiltInQProfile>> getQProfilesByLanguage(); | |||
} |
@@ -53,22 +53,22 @@ import static java.lang.String.format; | |||
import static org.apache.commons.lang.StringUtils.isNotEmpty; | |||
import static org.apache.commons.lang.StringUtils.lowerCase; | |||
public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository { | |||
private static final Logger LOGGER = Loggers.get(DefinedQProfileRepositoryImpl.class); | |||
public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository { | |||
private static final Logger LOGGER = Loggers.get(BuiltInQProfileRepositoryImpl.class); | |||
private static final String DEFAULT_PROFILE_NAME = "Sonar way"; | |||
private final Languages languages; | |||
private final List<ProfileDefinition> definitions; | |||
private Map<String, List<DefinedQProfile>> qProfilesByLanguage; | |||
private Map<String, List<BuiltInQProfile>> qProfilesByLanguage; | |||
/** | |||
* Requires for pico container when no {@link ProfileDefinition} is defined at all | |||
*/ | |||
public DefinedQProfileRepositoryImpl(Languages languages) { | |||
public BuiltInQProfileRepositoryImpl(Languages languages) { | |||
this(languages, new ProfileDefinition[0]); | |||
} | |||
public DefinedQProfileRepositoryImpl(Languages languages, ProfileDefinition... definitions) { | |||
public BuiltInQProfileRepositoryImpl(Languages languages, ProfileDefinition... definitions) { | |||
this.languages = languages; | |||
this.definitions = ImmutableList.copyOf(definitions); | |||
} | |||
@@ -85,7 +85,7 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
} | |||
@Override | |||
public Map<String, List<DefinedQProfile>> getQProfilesByLanguage() { | |||
public Map<String, List<BuiltInQProfile>> getQProfilesByLanguage() { | |||
checkState(qProfilesByLanguage != null, "initialize must be called first"); | |||
return qProfilesByLanguage; | |||
@@ -132,22 +132,22 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
}); | |||
} | |||
private static Map<String, List<DefinedQProfile>> toQualityProfilesByLanguage(ListMultimap<String, RulesProfile> rulesProfilesByLanguage) { | |||
Map<String, List<DefinedQProfile.Builder>> buildersByLanguage = Multimaps.asMap(rulesProfilesByLanguage) | |||
private static Map<String, List<BuiltInQProfile>> toQualityProfilesByLanguage(ListMultimap<String, RulesProfile> rulesProfilesByLanguage) { | |||
Map<String, List<BuiltInQProfile.Builder>> buildersByLanguage = Multimaps.asMap(rulesProfilesByLanguage) | |||
.entrySet() | |||
.stream() | |||
.collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, DefinedQProfileRepositoryImpl::toQualityProfileBuilders)); | |||
.collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, BuiltInQProfileRepositoryImpl::toQualityProfileBuilders)); | |||
return buildersByLanguage | |||
.entrySet() | |||
.stream() | |||
.filter(DefinedQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault) | |||
.filter(BuiltInQProfileRepositoryImpl::ensureAtMostOneDeclaredDefault) | |||
.filter(entry -> ensureParentExists(entry.getKey(), entry.getValue())) | |||
.collect(MoreCollectors.uniqueIndex(Map.Entry::getKey, entry -> toQualityProfiles(entry.getValue()), buildersByLanguage.size())); | |||
} | |||
private static boolean ensureParentExists(String language, List<DefinedQProfile.Builder> builders) { | |||
private static boolean ensureParentExists(String language, List<BuiltInQProfile.Builder> builders) { | |||
Set<String> qProfileNames = builders.stream() | |||
.map(DefinedQProfile.Builder::getName) | |||
.map(BuiltInQProfile.Builder::getName) | |||
.collect(MoreCollectors.toSet(builders.size())); | |||
builders | |||
.forEach(builder -> { | |||
@@ -160,21 +160,21 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
} | |||
/** | |||
* Creates {@link DefinedQProfile.Builder} for each unique quality profile name for a given language. | |||
* Creates {@link BuiltInQProfile.Builder} for each unique quality profile name for a given language. | |||
* Builders will have the following properties populated: | |||
* <ul> | |||
* <li>{@link DefinedQProfile.Builder#language language}: key of the method's parameter</li> | |||
* <li>{@link DefinedQProfile.Builder#name name}: {@link RulesProfile#getName()}</li> | |||
* <li>{@link DefinedQProfile.Builder#declaredDefault declaredDefault}: {@code true} if at least one RulesProfile | |||
* <li>{@link BuiltInQProfile.Builder#language language}: key of the method's parameter</li> | |||
* <li>{@link BuiltInQProfile.Builder#name name}: {@link RulesProfile#getName()}</li> | |||
* <li>{@link BuiltInQProfile.Builder#declaredDefault declaredDefault}: {@code true} if at least one RulesProfile | |||
* with a given name has {@link RulesProfile#getDefaultProfile()} is {@code true}</li> | |||
* <li>{@link DefinedQProfile.Builder#activeRules activeRules}: the concatenate of the active rules of all | |||
* <li>{@link BuiltInQProfile.Builder#activeRules activeRules}: the concatenate of the active rules of all | |||
* RulesProfile with a given name</li> | |||
* </ul> | |||
*/ | |||
private static List<DefinedQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, List<RulesProfile>> rulesProfilesByLanguage) { | |||
private static List<BuiltInQProfile.Builder> toQualityProfileBuilders(Map.Entry<String, List<RulesProfile>> rulesProfilesByLanguage) { | |||
String language = rulesProfilesByLanguage.getKey(); | |||
// use a LinkedHashMap to keep order of insertion of RulesProfiles | |||
Map<String, DefinedQProfile.Builder> qualityProfileBuildersByName = new LinkedHashMap<>(); | |||
Map<String, BuiltInQProfile.Builder> qualityProfileBuildersByName = new LinkedHashMap<>(); | |||
for (RulesProfile rulesProfile : rulesProfilesByLanguage.getValue()) { | |||
qualityProfileBuildersByName.compute( | |||
rulesProfile.getName(), | |||
@@ -184,21 +184,21 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
} | |||
/** | |||
* Fails if more than one {@link DefinedQProfile.Builder#declaredDefault} is {@code true}, otherwise returns {@code true}. | |||
* Fails if more than one {@link BuiltInQProfile.Builder#declaredDefault} is {@code true}, otherwise returns {@code true}. | |||
*/ | |||
private static boolean ensureAtMostOneDeclaredDefault(Map.Entry<String, List<DefinedQProfile.Builder>> entry) { | |||
private static boolean ensureAtMostOneDeclaredDefault(Map.Entry<String, List<BuiltInQProfile.Builder>> entry) { | |||
Set<String> declaredDefaultProfileNames = entry.getValue().stream() | |||
.filter(DefinedQProfile.Builder::isDeclaredDefault) | |||
.map(DefinedQProfile.Builder::getName) | |||
.filter(BuiltInQProfile.Builder::isDeclaredDefault) | |||
.map(BuiltInQProfile.Builder::getName) | |||
.collect(MoreCollectors.toSet()); | |||
checkState(declaredDefaultProfileNames.size() <= 1, "Several Quality profiles are flagged as default for the language %s: %s", entry.getKey(), declaredDefaultProfileNames); | |||
return true; | |||
} | |||
private static DefinedQProfile.Builder updateOrCreateBuilder(String language, @Nullable DefinedQProfile.Builder existingBuilder, RulesProfile rulesProfile) { | |||
DefinedQProfile.Builder builder = existingBuilder; | |||
private static BuiltInQProfile.Builder updateOrCreateBuilder(String language, @Nullable BuiltInQProfile.Builder existingBuilder, RulesProfile rulesProfile) { | |||
BuiltInQProfile.Builder builder = existingBuilder; | |||
if (builder == null) { | |||
builder = new DefinedQProfile.Builder() | |||
builder = new BuiltInQProfile.Builder() | |||
.setLanguage(language) | |||
.setName(rulesProfile.getName()) | |||
.setParentName(rulesProfile.getParentName()); | |||
@@ -212,9 +212,9 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
.addRules(rulesProfile.getActiveRules()); | |||
} | |||
private static List<DefinedQProfile> toQualityProfiles(List<DefinedQProfile.Builder> builders) { | |||
if (builders.stream().noneMatch(DefinedQProfile.Builder::isDeclaredDefault)) { | |||
Optional<DefinedQProfile.Builder> sonarWayProfile = builders.stream().filter(builder -> builder.getName().equals(DEFAULT_PROFILE_NAME)).findFirst(); | |||
private static List<BuiltInQProfile> toQualityProfiles(List<BuiltInQProfile.Builder> builders) { | |||
if (builders.stream().noneMatch(BuiltInQProfile.Builder::isDeclaredDefault)) { | |||
Optional<BuiltInQProfile.Builder> sonarWayProfile = builders.stream().filter(builder -> builder.getName().equals(DEFAULT_PROFILE_NAME)).findFirst(); | |||
if (sonarWayProfile.isPresent()) { | |||
sonarWayProfile.get().setComputedDefault(true); | |||
} else { | |||
@@ -229,19 +229,19 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
} | |||
@VisibleForTesting | |||
static class SortByParentName implements Comparator<DefinedQProfile.Builder> { | |||
private final Map<String, DefinedQProfile.Builder> buildersByName; | |||
static class SortByParentName implements Comparator<BuiltInQProfile.Builder> { | |||
private final Map<String, BuiltInQProfile.Builder> buildersByName; | |||
@VisibleForTesting | |||
final Map<String, Integer> depthByBuilder; | |||
@VisibleForTesting | |||
SortByParentName(Collection<DefinedQProfile.Builder> builders) { | |||
SortByParentName(Collection<BuiltInQProfile.Builder> builders) { | |||
this.buildersByName = builders.stream() | |||
.collect(MoreCollectors.uniqueIndex(DefinedQProfile.Builder::getName, Function.identity(), builders.size())); | |||
.collect(MoreCollectors.uniqueIndex(BuiltInQProfile.Builder::getName, Function.identity(), builders.size())); | |||
this.depthByBuilder = buildDepthByBuilder(buildersByName, builders); | |||
} | |||
private static Map<String, Integer> buildDepthByBuilder(Map<String, DefinedQProfile.Builder> buildersByName, Collection<DefinedQProfile.Builder> builders) { | |||
private static Map<String, Integer> buildDepthByBuilder(Map<String, BuiltInQProfile.Builder> buildersByName, Collection<BuiltInQProfile.Builder> builders) { | |||
Map<String, Integer> depthByBuilder = new HashMap<>(); | |||
builders.forEach(builder -> depthByBuilder.put(builder.getName(), 0)); | |||
builders | |||
@@ -251,8 +251,8 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
return ImmutableMap.copyOf(depthByBuilder); | |||
} | |||
private static void increaseDepth(Map<String, DefinedQProfile.Builder> buildersByName, Map<String, Integer> maps, DefinedQProfile.Builder builder) { | |||
DefinedQProfile.Builder parent = buildersByName.get(builder.getParentName()); | |||
private static void increaseDepth(Map<String, BuiltInQProfile.Builder> buildersByName, Map<String, Integer> maps, BuiltInQProfile.Builder builder) { | |||
BuiltInQProfile.Builder parent = buildersByName.get(builder.getParentName()); | |||
if (parent.getParentName() != null) { | |||
increaseDepth(buildersByName, maps, parent); | |||
} | |||
@@ -260,7 +260,7 @@ public class DefinedQProfileRepositoryImpl implements DefinedQProfileRepository | |||
} | |||
@Override | |||
public int compare(DefinedQProfile.Builder o1, DefinedQProfile.Builder o2) { | |||
public int compare(BuiltInQProfile.Builder o1, BuiltInQProfile.Builder o2) { | |||
return depthByBuilder.getOrDefault(o1.getName(), 0) - depthByBuilder.getOrDefault(o2.getName(), 0); | |||
} | |||
} |
@@ -20,7 +20,7 @@ | |||
package org.sonar.server.qualityprofile; | |||
/** | |||
* Marker interface of any implementation of {@link DefinedQProfileCreation} which supports caching. | |||
* Marker interface of any implementation of {@link BuiltInQProfileCreation} which supports caching. | |||
*/ | |||
public interface CachingDefinedQProfileCreation extends DefinedQProfileCreation { | |||
public interface CachingBuiltInQProfileCreation extends BuiltInQProfileCreation { | |||
} |
@@ -21,8 +21,8 @@ package org.sonar.server.qualityprofile; | |||
import org.sonar.db.DbClient; | |||
public class CachingDefinedQProfileCreationImpl extends DefinedQProfileCreationImpl implements CachingDefinedQProfileCreation { | |||
public CachingDefinedQProfileCreationImpl(DbClient dbClient, QProfileFactory profileFactory, CachingRuleActivator ruleActivator) { | |||
public class CachingBuiltInQProfileCreationImpl extends BuiltInQProfileCreationImpl implements CachingBuiltInQProfileCreation { | |||
public CachingBuiltInQProfileCreationImpl(DbClient dbClient, QProfileFactory profileFactory, CachingRuleActivator ruleActivator) { | |||
super(dbClient, profileFactory, ruleActivator); | |||
} | |||
} |
@@ -49,16 +49,16 @@ public class MassRegisterQualityProfiles { | |||
private static final Pagination PROCESSED_ORGANIZATIONS_BATCH_SIZE = forPage(1).andSize(2000); | |||
private final Settings settings; | |||
private final DefinedQProfileRepository definedQProfileRepository; | |||
private final BuiltInQProfileRepository builtInQProfileRepository; | |||
private final DbClient dbClient; | |||
private final DefinedQProfileInsert definedQProfileInsert; | |||
private final BuiltInQProfileInsert builtInQProfileInsert; | |||
public MassRegisterQualityProfiles(Settings settings, DefinedQProfileRepository definedQProfileRepository, | |||
DbClient dbClient, DefinedQProfileInsert definedQProfileInsert) { | |||
public MassRegisterQualityProfiles(Settings settings, BuiltInQProfileRepository builtInQProfileRepository, | |||
DbClient dbClient, BuiltInQProfileInsert builtInQProfileInsert) { | |||
this.settings = settings; | |||
this.definedQProfileRepository = definedQProfileRepository; | |||
this.builtInQProfileRepository = builtInQProfileRepository; | |||
this.dbClient = dbClient; | |||
this.definedQProfileInsert = definedQProfileInsert; | |||
this.builtInQProfileInsert = builtInQProfileInsert; | |||
} | |||
public void start() { | |||
@@ -67,23 +67,23 @@ public class MassRegisterQualityProfiles { | |||
} | |||
Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Mass Register quality profiles"); | |||
if (definedQProfileRepository.getQProfilesByLanguage().isEmpty()) { | |||
if (builtInQProfileRepository.getQProfilesByLanguage().isEmpty()) { | |||
return; | |||
} | |||
try (DbSession session = dbClient.openSession(false); | |||
DbSession batchSession = dbClient.openSession(true)) { | |||
definedQProfileRepository.getQProfilesByLanguage() | |||
builtInQProfileRepository.getQProfilesByLanguage() | |||
.forEach((key, value) -> registerPerLanguage(session, batchSession, value)); | |||
profiler.stopDebug(); | |||
} | |||
} | |||
private void registerPerLanguage(DbSession session, DbSession batchSession, List<DefinedQProfile> qualityProfiles) { | |||
private void registerPerLanguage(DbSession session, DbSession batchSession, List<BuiltInQProfile> qualityProfiles) { | |||
qualityProfiles.forEach(qp -> registerPerQualityProfile(session, batchSession, qp)); | |||
} | |||
private void registerPerQualityProfile(DbSession session, DbSession batchSession, DefinedQProfile qualityProfile) { | |||
private void registerPerQualityProfile(DbSession session, DbSession batchSession, BuiltInQProfile qualityProfile) { | |||
LOGGER.info("Register profile {}", qualityProfile.getQProfileName()); | |||
Profiler profiler = Profiler.create(Loggers.get(getClass())); | |||
@@ -93,21 +93,21 @@ public class MassRegisterQualityProfiles { | |||
} | |||
} | |||
private List<OrganizationDto> getOrganizationsWithoutQP(DbSession session, DefinedQProfile qualityProfile) { | |||
private List<OrganizationDto> getOrganizationsWithoutQP(DbSession session, BuiltInQProfile qualityProfile) { | |||
return dbClient.organizationDao().selectOrganizationsWithoutLoadedTemplate(session, | |||
qualityProfile.getLoadedTemplateType(), PROCESSED_ORGANIZATIONS_BATCH_SIZE); | |||
} | |||
private void registerPerQualityProfileAndOrganization(DbSession session, DbSession batchSession, | |||
DefinedQProfile definedQProfile, OrganizationDto organization, Profiler profiler) { | |||
BuiltInQProfile builtInQProfile, OrganizationDto organization, Profiler profiler) { | |||
profiler.start(); | |||
definedQProfileInsert.create(session, batchSession, definedQProfile, organization); | |||
builtInQProfileInsert.create(session, batchSession, builtInQProfile, organization); | |||
session.commit(); | |||
batchSession.commit(); | |||
profiler.stopDebug(format("Register profile %s for organization %s", definedQProfile.getQProfileName(), organization.getKey())); | |||
profiler.stopDebug(format("Register profile %s for organization %s", builtInQProfile.getQProfileName(), organization.getKey())); | |||
} | |||
} |
@@ -121,7 +121,7 @@ public class QProfileBackuperImpl implements QProfileBackuper { | |||
if (overriddenProfileName != null) { | |||
targetName = new QProfileName(nameInBackup.getLanguage(), overriddenProfileName); | |||
} | |||
return profileFactory.getOrCreate(dbSession, organization, targetName); | |||
return profileFactory.getOrCreateCustom(dbSession, organization, targetName); | |||
}); | |||
} | |||
@@ -70,7 +70,7 @@ public class QProfileCopier { | |||
verify(sourceProfile, toProfileName); | |||
QualityProfileDto toProfile = db.qualityProfileDao().selectByNameAndLanguage(organization, toProfileName.getName(), toProfileName.getLanguage(), dbSession); | |||
if (toProfile == null) { | |||
toProfile = factory.checkAndCreate(dbSession, organization, toProfileName); | |||
toProfile = factory.checkAndCreateCustom(dbSession, organization, toProfileName); | |||
toProfile.setParentKee(sourceProfile.getParentKee()); | |||
db.qualityProfileDao().update(dbSession, toProfile); | |||
dbSession.commit(); |
@@ -54,11 +54,11 @@ public class QProfileFactory { | |||
// ------------- CREATION | |||
QualityProfileDto getOrCreate(DbSession dbSession, OrganizationDto organization, QProfileName name) { | |||
QualityProfileDto getOrCreateCustom(DbSession dbSession, OrganizationDto organization, QProfileName name) { | |||
requireNonNull(organization); | |||
QualityProfileDto profile = db.qualityProfileDao().selectByNameAndLanguage(organization, name.getName(), name.getLanguage(), dbSession); | |||
if (profile == null) { | |||
profile = doCreate(dbSession, organization, name, false); | |||
profile = doCreate(dbSession, organization, name, false, false); | |||
} | |||
return profile; | |||
} | |||
@@ -68,11 +68,11 @@ public class QProfileFactory { | |||
* | |||
* @throws BadRequestException if a quality profile with the specified name already exists | |||
*/ | |||
public QualityProfileDto checkAndCreate(DbSession dbSession, OrganizationDto organization, QProfileName name) { | |||
public QualityProfileDto checkAndCreateCustom(DbSession dbSession, OrganizationDto organization, QProfileName name) { | |||
requireNonNull(organization); | |||
QualityProfileDto dto = db.qualityProfileDao().selectByNameAndLanguage(organization, name.getName(), name.getLanguage(), dbSession); | |||
checkRequest(dto == null, "Quality profile already exists: %s", name); | |||
return doCreate(dbSession, organization, name, false); | |||
return doCreate(dbSession, organization, name, false, false); | |||
} | |||
/** | |||
@@ -80,8 +80,8 @@ public class QProfileFactory { | |||
* | |||
* A DB error will be thrown if the quality profile already exists. | |||
*/ | |||
public QualityProfileDto create(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault) { | |||
return doCreate(dbSession, requireNonNull(organization), name, isDefault); | |||
public QualityProfileDto createBuiltIn(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault) { | |||
return doCreate(dbSession, requireNonNull(organization), name, isDefault, true); | |||
} | |||
private static OrganizationDto requireNonNull(@Nullable OrganizationDto organization) { | |||
@@ -89,7 +89,7 @@ public class QProfileFactory { | |||
return organization; | |||
} | |||
private QualityProfileDto doCreate(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault) { | |||
private QualityProfileDto doCreate(DbSession dbSession, OrganizationDto organization, QProfileName name, boolean isDefault, boolean isBuiltIn) { | |||
if (StringUtils.isEmpty(name.getName())) { | |||
throw BadRequestException.create("quality_profiles.profile_name_cant_be_blank"); | |||
} | |||
@@ -99,6 +99,7 @@ public class QProfileFactory { | |||
.setOrganizationUuid(organization.getUuid()) | |||
.setLanguage(name.getLanguage()) | |||
.setDefault(isDefault) | |||
.setIsBuiltIn(isBuiltIn) | |||
.setRulesUpdatedAtAsDate(now); | |||
db.qualityProfileDao().insert(dbSession, dto); | |||
return dto; |
@@ -49,33 +49,33 @@ public class QProfileResetImpl implements QProfileReset { | |||
private final QProfileFactory factory; | |||
private final RuleActivator activator; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
private final DefinedQProfileRepository definedQProfileRepositories; | |||
private final BuiltInQProfileRepository builtInQProfileRepositories; | |||
public QProfileResetImpl(DbClient db, RuleActivator activator, ActiveRuleIndexer activeRuleIndexer, QProfileFactory factory, | |||
DefinedQProfileRepository definedQProfileRepository) { | |||
BuiltInQProfileRepository builtInQProfileRepository) { | |||
this.db = db; | |||
this.activator = activator; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
this.factory = factory; | |||
this.definedQProfileRepositories = definedQProfileRepository; | |||
this.builtInQProfileRepositories = builtInQProfileRepository; | |||
} | |||
@Override | |||
public void resetLanguage(DbSession dbSession, OrganizationDto organization, String language) { | |||
definedQProfileRepositories.getQProfilesByLanguage() | |||
builtInQProfileRepositories.getQProfilesByLanguage() | |||
.entrySet() | |||
.stream() | |||
.filter(entry -> entry.getKey().equals(language)) | |||
.map(Map.Entry::getValue) | |||
.flatMap(List::stream) | |||
.forEach(definedQProfile -> resetProfile(dbSession, organization, definedQProfile)); | |||
.forEach(builtInQProfile -> resetProfile(dbSession, organization, builtInQProfile)); | |||
} | |||
private void resetProfile(DbSession dbSession, OrganizationDto organization, DefinedQProfile definedQProfile) { | |||
QualityProfileDto profile = factory.getOrCreate(dbSession, organization, definedQProfile.getQProfileName()); | |||
private void resetProfile(DbSession dbSession, OrganizationDto organization, BuiltInQProfile builtInQProfile) { | |||
QualityProfileDto profile = factory.getOrCreateCustom(dbSession, organization, builtInQProfile.getQProfileName()); | |||
List<RuleActivation> activations = Lists.newArrayList(); | |||
definedQProfile.getActiveRules().forEach(activeRule -> activations.add(getRuleActivation(dbSession, activeRule))); | |||
builtInQProfile.getActiveRules().forEach(activeRule -> activations.add(getRuleActivation(dbSession, activeRule))); | |||
reset(dbSession, profile, activations); | |||
} | |||
@@ -20,6 +20,7 @@ | |||
package org.sonar.server.qualityprofile; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import org.sonar.api.server.ServerSide; | |||
import org.sonar.api.utils.log.Logger; | |||
@@ -42,16 +43,16 @@ public class RegisterQualityProfiles { | |||
private static final Logger LOGGER = Loggers.get(RegisterQualityProfiles.class); | |||
private static final Pagination PROCESSED_ORGANIZATIONS_BATCH_SIZE = forPage(1).andSize(2000); | |||
private final DefinedQProfileRepository definedQProfileRepository; | |||
private final BuiltInQProfileRepository builtInQProfileRepository; | |||
private final DbClient dbClient; | |||
private final DefinedQProfileCreation definedQProfileCreation; | |||
private final BuiltInQProfileCreation builtInQProfileCreation; | |||
private final ActiveRuleIndexer activeRuleIndexer; | |||
public RegisterQualityProfiles(DefinedQProfileRepository definedQProfileRepository, | |||
DbClient dbClient, DefinedQProfileCreation definedQProfileCreation, ActiveRuleIndexer activeRuleIndexer) { | |||
this.definedQProfileRepository = definedQProfileRepository; | |||
public RegisterQualityProfiles(BuiltInQProfileRepository builtInQProfileRepository, | |||
DbClient dbClient, BuiltInQProfileCreation builtInQProfileCreation, ActiveRuleIndexer activeRuleIndexer) { | |||
this.builtInQProfileRepository = builtInQProfileRepository; | |||
this.dbClient = dbClient; | |||
this.definedQProfileCreation = definedQProfileCreation; | |||
this.builtInQProfileCreation = builtInQProfileCreation; | |||
this.activeRuleIndexer = activeRuleIndexer; | |||
} | |||
@@ -60,36 +61,57 @@ public class RegisterQualityProfiles { | |||
try (DbSession session = dbClient.openSession(false)) { | |||
List<ActiveRuleChange> changes = new ArrayList<>(); | |||
definedQProfileRepository.getQProfilesByLanguage().entrySet() | |||
.forEach(entry -> registerPerLanguage(session, entry.getValue(), changes)); | |||
builtInQProfileRepository.getQProfilesByLanguage().forEach( | |||
(key, value) -> registerPerLanguage(session, value, changes)); | |||
activeRuleIndexer.index(changes); | |||
profiler.stopDebug(); | |||
} | |||
} | |||
private void registerPerLanguage(DbSession session, List<DefinedQProfile> qualityProfiles, List<ActiveRuleChange> changes) { | |||
private void registerPerLanguage(DbSession session, List<BuiltInQProfile> qualityProfiles, List<ActiveRuleChange> changes) { | |||
qualityProfiles.forEach(qp -> registerPerQualityProfile(session, qp, changes)); | |||
session.commit(); | |||
} | |||
private void registerPerQualityProfile(DbSession session, DefinedQProfile qualityProfile, List<ActiveRuleChange> changes) { | |||
private void registerPerQualityProfile(DbSession dbSession, BuiltInQProfile qualityProfile, List<ActiveRuleChange> changes) { | |||
LOGGER.info("Register profile {}", qualityProfile.getQProfileName()); | |||
renameOutdatedProfiles(dbSession, qualityProfile); | |||
List<OrganizationDto> organizationDtos; | |||
while (!(organizationDtos = getOrganizationsWithoutQP(session, qualityProfile)).isEmpty()) { | |||
organizationDtos.forEach(organization -> registerPerQualityProfileAndOrganization(session, qualityProfile, organization, changes)); | |||
while (!(organizationDtos = getOrganizationsWithoutQP(dbSession, qualityProfile)).isEmpty()) { | |||
organizationDtos.forEach(organization -> registerPerQualityProfileAndOrganization(dbSession, qualityProfile, organization, changes)); | |||
} | |||
} | |||
/** | |||
* The Quality profiles created by users should be renamed when they have the same name | |||
* as the built-in profile to be persisted. | |||
* | |||
* When upgrading from < 6.5 , all existing profiles are considered as "custom" (created | |||
* by users) because the concept of built-in profile is not persisted. The "Sonar way" profiles | |||
* are renamed to "Sonar way (outdated copy) in order to avoid conflicts with the new | |||
* built-in profile "Sonar way", which has probably different configuration. | |||
*/ | |||
private void renameOutdatedProfiles(DbSession dbSession, BuiltInQProfile profile) { | |||
Collection<String> profileKeys = dbClient.qualityProfileDao().selectOutdatedProfiles(dbSession, profile.getLanguage(), profile.getName()); | |||
if (profileKeys.isEmpty()) { | |||
return; | |||
} | |||
String newName = profile.getName() + " (outdated copy)"; | |||
LOGGER.info("Rename Quality profiles [{}/{}] to [{}] in {} organizations", profile.getLanguage(), profile.getName(), newName, profileKeys.size()); | |||
dbClient.qualityProfileDao().renameAndCommit(dbSession, profileKeys, newName); | |||
} | |||
private List<OrganizationDto> getOrganizationsWithoutQP(DbSession session, DefinedQProfile qualityProfile) { | |||
private List<OrganizationDto> getOrganizationsWithoutQP(DbSession session, BuiltInQProfile qualityProfile) { | |||
return dbClient.organizationDao().selectOrganizationsWithoutLoadedTemplate(session, | |||
qualityProfile.getLoadedTemplateType(), PROCESSED_ORGANIZATIONS_BATCH_SIZE); | |||
} | |||
private void registerPerQualityProfileAndOrganization(DbSession session, DefinedQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
private void registerPerQualityProfileAndOrganization(DbSession session, BuiltInQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
LOGGER.debug("Register profile {} for organization {}", qualityProfile.getQProfileName(), organization.getKey()); | |||
definedQProfileCreation.create(session, qualityProfile, organization, changes); | |||
builtInQProfileCreation.create(session, qualityProfile, organization, changes); | |||
session.commit(); | |||
} | |||
@@ -123,7 +123,7 @@ public class CreateAction implements QProfileWsAction { | |||
private CreateWsResponse doHandle(DbSession dbSession, CreateRequest createRequest, Request request, OrganizationDto organization) { | |||
QProfileResult result = new QProfileResult(); | |||
QualityProfileDto profile = profileFactory.checkAndCreate(dbSession, organization, | |||
QualityProfileDto profile = profileFactory.checkAndCreateCustom(dbSession, organization, | |||
QProfileName.createFor(createRequest.getLanguage(), createRequest.getProfileName())); | |||
result.setProfile(profile); | |||
for (ProfileImporter importer : importers) { |
@@ -50,9 +50,9 @@ import org.sonar.server.es.EsTester; | |||
import org.sonar.server.es.SearchOptions; | |||
import org.sonar.server.language.LanguageTesting; | |||
import org.sonar.server.qualityprofile.ActiveRuleChange; | |||
import org.sonar.server.qualityprofile.DefinedQProfile; | |||
import org.sonar.server.qualityprofile.DefinedQProfileInsertRule; | |||
import org.sonar.server.qualityprofile.DefinedQProfileRepositoryRule; | |||
import org.sonar.server.qualityprofile.BuiltInQProfile; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsertRule; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryRule; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.user.index.UserIndex; | |||
import org.sonar.server.user.index.UserIndexDefinition; | |||
@@ -94,9 +94,9 @@ public class OrganizationCreationImplTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public DefinedQProfileRepositoryRule definedQProfileRepositoryRule = new DefinedQProfileRepositoryRule(); | |||
public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule(); | |||
@Rule | |||
public DefinedQProfileInsertRule definedQProfileCreationRule = new DefinedQProfileInsertRule(); | |||
public BuiltInQProfileInsertRule builtInQProfileCreationRule = new BuiltInQProfileInsertRule(); | |||
private DbSession dbSession = dbTester.getSession(); | |||
@@ -110,7 +110,7 @@ public class OrganizationCreationImplTest { | |||
private DefaultGroupCreator defaultGroupCreator = new DefaultGroupCreatorImpl(dbClient); | |||
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private OrganizationCreationImpl underTest = new OrganizationCreationImpl(dbClient, system2, uuidFactory, organizationValidation, settings, userIndexer, | |||
definedQProfileRepositoryRule, definedQProfileCreationRule, defaultGroupCreator, activeRuleIndexer); | |||
builtInQProfileRepositoryRule, builtInQProfileCreationRule, defaultGroupCreator, activeRuleIndexer); | |||
private UserDto someUser; | |||
@@ -167,7 +167,7 @@ public class OrganizationCreationImplTest { | |||
} | |||
@Test | |||
public void create_fails_with_ISE_if_DefinedQProfileRepository_has_not_been_initialized() throws OrganizationCreation.KeyConflictException { | |||
public void create_fails_with_ISE_if_BuiltInQProfileRepository_has_not_been_initialized() throws OrganizationCreation.KeyConflictException { | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
expectedException.expect(IllegalStateException.class); | |||
@@ -189,7 +189,7 @@ public class OrganizationCreationImplTest { | |||
@Test | |||
public void create_creates_unguarded_organization_with_properties_from_NewOrganization_arg() throws OrganizationCreation.KeyConflictException { | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.create(dbSession, someUser, FULL_POPULATED_NEW_ORGANIZATION); | |||
@@ -210,7 +210,7 @@ public class OrganizationCreationImplTest { | |||
public void create_creates_owners_group_with_all_permissions_for_new_organization_and_add_current_user_to_it() throws OrganizationCreation.KeyConflictException { | |||
UserDto user = dbTester.users().insertUser(); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION); | |||
@@ -221,7 +221,7 @@ public class OrganizationCreationImplTest { | |||
public void create_creates_members_group_and_add_current_user_to_it() throws OrganizationCreation.KeyConflictException { | |||
UserDto user = dbTester.users().insertUser(); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION); | |||
@@ -231,7 +231,7 @@ public class OrganizationCreationImplTest { | |||
@Test | |||
public void create_does_not_require_description_url_and_avatar_to_be_non_null() throws OrganizationCreation.KeyConflictException { | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.create(dbSession, someUser, newOrganizationBuilder() | |||
.setKey("key") | |||
@@ -251,7 +251,7 @@ public class OrganizationCreationImplTest { | |||
@Test | |||
public void create_creates_default_template_for_new_organization() throws OrganizationCreation.KeyConflictException { | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.create(dbSession, someUser, FULL_POPULATED_NEW_ORGANIZATION); | |||
@@ -277,7 +277,7 @@ public class OrganizationCreationImplTest { | |||
userIndexer.index(user.getLogin()); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
userIndexer.index(someUser.getLogin()); | |||
underTest.create(dbSession, someUser, FULL_POPULATED_NEW_ORGANIZATION); | |||
@@ -287,26 +287,26 @@ public class OrganizationCreationImplTest { | |||
} | |||
@Test | |||
public void create_creates_QualityProfile_for_each_DefinedQProfile_in_repository_and_index_ActiveRule_changes_in_order() throws OrganizationCreation.KeyConflictException { | |||
DefinedQProfile definedQProfile1 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp1"); | |||
DefinedQProfile definedQProfile2 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp2"); | |||
DefinedQProfile definedQProfile3 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp3"); | |||
DefinedQProfile definedQProfile4 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp4"); | |||
definedQProfileRepositoryRule.initialize(); | |||
public void create_creates_QualityProfile_for_each_BuiltInQProfile_in_repository_and_index_ActiveRule_changes_in_order() throws OrganizationCreation.KeyConflictException { | |||
BuiltInQProfile builtInQProfile1 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp1"); | |||
BuiltInQProfile builtInQProfile2 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp2"); | |||
BuiltInQProfile builtInQProfile3 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp3"); | |||
BuiltInQProfile builtInQProfile4 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp4"); | |||
builtInQProfileRepositoryRule.initialize(); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
underTest.create(dbSession, someUser, FULL_POPULATED_NEW_ORGANIZATION); | |||
OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get(); | |||
assertThat(definedQProfileCreationRule.getCallLogs()) | |||
assertThat(builtInQProfileCreationRule.getCallLogs()) | |||
.hasSize(4) | |||
.extracting(DefinedQProfileInsertRule.CallLog::getOrganizationDto) | |||
.extracting(BuiltInQProfileInsertRule.CallLog::getOrganizationDto) | |||
.extracting(OrganizationDto::getUuid) | |||
.containsOnly(organization.getUuid()); | |||
assertThat(definedQProfileCreationRule.getCallLogs()) | |||
.extracting(DefinedQProfileInsertRule.CallLog::getDefinedQProfile) | |||
.extracting(DefinedQProfile::getName) | |||
.containsExactly(definedQProfile1.getName(), definedQProfile2.getName(), definedQProfile3.getName(), definedQProfile4.getName()); | |||
assertThat(builtInQProfileCreationRule.getCallLogs()) | |||
.extracting(BuiltInQProfileInsertRule.CallLog::getDefinedQProfile) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly(builtInQProfile1.getName(), builtInQProfile2.getName(), builtInQProfile3.getName(), builtInQProfile4.getName()); | |||
} | |||
@Test | |||
@@ -344,7 +344,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -382,7 +382,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -397,7 +397,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -410,7 +410,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -438,7 +438,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -453,7 +453,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -469,7 +469,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(login)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -485,7 +485,7 @@ public class OrganizationCreationImplTest { | |||
when(organizationValidation.generateKeyFrom(login)).thenReturn(SLUG_OF_A_LOGIN); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.createForUser(dbSession, user); | |||
@@ -498,26 +498,26 @@ public class OrganizationCreationImplTest { | |||
public void createForUser_creates_QualityProfile_for_each_DefinedQProfile_in_repository_and_index_ActiveRule_changes_in_order() throws OrganizationCreation.KeyConflictException { | |||
UserDto user = dbTester.users().insertUser(A_LOGIN); | |||
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); | |||
DefinedQProfile definedQProfile1 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp1"); | |||
DefinedQProfile definedQProfile2 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp2"); | |||
DefinedQProfile definedQProfile3 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp3"); | |||
DefinedQProfile definedQProfile4 = definedQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp4"); | |||
definedQProfileRepositoryRule.initialize(); | |||
BuiltInQProfile builtInQProfile1 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp1"); | |||
BuiltInQProfile builtInQProfile2 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp2"); | |||
BuiltInQProfile builtInQProfile3 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp3"); | |||
BuiltInQProfile builtInQProfile4 = builtInQProfileRepositoryRule.add(LanguageTesting.newLanguage("foo"), "qp4"); | |||
builtInQProfileRepositoryRule.initialize(); | |||
mockForSuccessfulInsert(SOME_UUID, SOME_DATE); | |||
enableCreatePersonalOrg(true); | |||
underTest.createForUser(dbSession, user); | |||
OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get(); | |||
assertThat(definedQProfileCreationRule.getCallLogs()) | |||
assertThat(builtInQProfileCreationRule.getCallLogs()) | |||
.hasSize(4) | |||
.extracting(DefinedQProfileInsertRule.CallLog::getOrganizationDto) | |||
.extracting(BuiltInQProfileInsertRule.CallLog::getOrganizationDto) | |||
.extracting(OrganizationDto::getUuid) | |||
.containsOnly(organization.getUuid()); | |||
assertThat(definedQProfileCreationRule.getCallLogs()) | |||
.extracting(DefinedQProfileInsertRule.CallLog::getDefinedQProfile) | |||
.extracting(DefinedQProfile::getName) | |||
.containsExactly(definedQProfile1.getName(), definedQProfile2.getName(), definedQProfile3.getName(), definedQProfile4.getName()); | |||
assertThat(builtInQProfileCreationRule.getCallLogs()) | |||
.extracting(BuiltInQProfileInsertRule.CallLog::getDefinedQProfile) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly(builtInQProfile1.getName(), builtInQProfile2.getName(), builtInQProfile3.getName(), builtInQProfile4.getName()); | |||
} | |||
private static ActiveRuleChange newActiveRuleChange(String id) { |
@@ -55,8 +55,8 @@ import org.sonar.server.organization.OrganizationCreationImpl; | |||
import org.sonar.server.organization.OrganizationValidation; | |||
import org.sonar.server.organization.OrganizationValidationImpl; | |||
import org.sonar.server.organization.TestOrganizationFlags; | |||
import org.sonar.server.qualityprofile.DefinedQProfileInsert; | |||
import org.sonar.server.qualityprofile.DefinedQProfileRepository; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileInsert; | |||
import org.sonar.server.qualityprofile.BuiltInQProfileRepository; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.user.index.UserIndex; | |||
@@ -103,7 +103,7 @@ public class CreateActionTest { | |||
private UserIndex userIndex = new UserIndex(es.client()); | |||
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private OrganizationCreation organizationCreation = new OrganizationCreationImpl(dbClient, system2, uuidFactory, organizationValidation, settings, userIndexer, | |||
mock(DefinedQProfileRepository.class), mock(DefinedQProfileInsert.class), new DefaultGroupCreatorImpl(dbClient), activeRuleIndexer); | |||
mock(BuiltInQProfileRepository.class), mock(BuiltInQProfileInsert.class), new DefaultGroupCreatorImpl(dbClient), activeRuleIndexer); | |||
private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone().setEnabled(true); | |||
private UserDto user; |
@@ -59,7 +59,7 @@ import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.core.util.UtcDateUtils.formatDateTime; | |||
public class DefinedQProfileCreationImplTest { | |||
public class BuiltInQProfileCreationImplTest { | |||
private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo"); | |||
private static final String TABLE_RULES_PROFILES = "RULES_PROFILES"; | |||
private static final String TABLE_LOADED_TEMPLATES = "loaded_templates"; | |||
@@ -69,7 +69,7 @@ public class DefinedQProfileCreationImplTest { | |||
@Rule | |||
public UserSessionRule userSessionRule = UserSessionRule.standalone(); | |||
@Rule | |||
public DefinedQProfileRepositoryRule definedQProfileRepositoryRule = new DefinedQProfileRepositoryRule(); | |||
public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule(); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private DbSession dbSession = dbClient.openSession(false); | |||
@@ -77,7 +77,7 @@ public class DefinedQProfileCreationImplTest { | |||
private System2 mockedSystem2 = mock(System2.class); | |||
private RuleActivator mockedRuleActivator = mock(RuleActivator.class); | |||
private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private DefinedQProfileCreationImpl underTest = new DefinedQProfileCreationImpl( | |||
private BuiltInQProfileCreationImpl underTest = new BuiltInQProfileCreationImpl( | |||
dbClient, | |||
new QProfileFactory(dbClient, mockedUuidFactory, mockedSystem2, activeRuleIndexer), | |||
mockedRuleActivator); | |||
@@ -91,12 +91,12 @@ public class DefinedQProfileCreationImplTest { | |||
@Test | |||
public void create_creates_qp_and_store_flag_in_loaded_templates_for_specified_organization() { | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", false); | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", false); | |||
long date = 2_456_789L; | |||
String uuid = "uuid 1"; | |||
mockForSingleQPInsert(uuid, date); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
QualityProfileDto dto = getPersistedQP(organization, FOO_LANGUAGE, "foo1"); | |||
@@ -113,7 +113,7 @@ public class DefinedQProfileCreationImplTest { | |||
assertThat(dto.isDefault()).isFalse(); | |||
assertThat(dbTester.countRowsOfTable(dbTester.getSession(), TABLE_RULES_PROFILES)).isEqualTo(1); | |||
assertThat(dbClient.loadedTemplateDao().countByTypeAndKey(definedQProfile.getLoadedTemplateType(), organization.getUuid(), dbTester.getSession())) | |||
assertThat(dbClient.loadedTemplateDao().countByTypeAndKey(builtInQProfile.getLoadedTemplateType(), organization.getUuid(), dbTester.getSession())) | |||
.isEqualTo(1); | |||
assertThat(dbTester.countRowsOfTable(dbTester.getSession(), TABLE_LOADED_TEMPLATES)).isEqualTo(1); | |||
assertThat(activeRuleChanges).isEmpty(); | |||
@@ -122,10 +122,10 @@ public class DefinedQProfileCreationImplTest { | |||
@Test | |||
public void create_persists_default_flag_of_DefinedQProfile() { | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true); | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true); | |||
mockForSingleQPInsert(); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
assertThat(getPersistedQP(organization, FOO_LANGUAGE, "foo1").isDefault()).isTrue(); | |||
@@ -135,17 +135,17 @@ public class DefinedQProfileCreationImplTest { | |||
@Test | |||
public void create_does_not_update_existing_profile_if_it_already_exists() { | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", false); | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", false); | |||
long date = 2_456_789L; | |||
String uuid = "uuid 1"; | |||
mockForSingleQPInsert(uuid, date); | |||
QualityProfileDto existing = dbTester.qualityProfiles().insertQualityProfile( | |||
QualityProfileDto.createFor("a key") | |||
.setName(definedQProfile.getName()) | |||
.setLanguage(definedQProfile.getLanguage()) | |||
.setName(builtInQProfile.getName()) | |||
.setLanguage(builtInQProfile.getLanguage()) | |||
.setOrganizationUuid(organization.getUuid())); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
QualityProfileDto dto = getPersistedQP(organization, FOO_LANGUAGE, "foo1"); | |||
@@ -166,12 +166,12 @@ public class DefinedQProfileCreationImplTest { | |||
asList(changes[2], changes[3])); | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, | |||
activeRule("A", RulePriority.INFO), activeRule("B", RulePriority.MINOR), activeRule("C", RulePriority.MAJOR), | |||
activeRule("D", RulePriority.CRITICAL), activeRule("E", RulePriority.BLOCKER)); | |||
mockForSingleQPInsert(); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
assertThat(callLogs) | |||
@@ -187,10 +187,10 @@ public class DefinedQProfileCreationImplTest { | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
ActiveRule activeRule = activeRule("A", RulePriority.BLOCKER); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, activeRule); | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, activeRule); | |||
mockForSingleQPInsert(); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
assertThat(callLogs) | |||
@@ -213,12 +213,12 @@ public class DefinedQProfileCreationImplTest { | |||
Collections.emptyList()); | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, | |||
activeRule("A", RulePriority.INFO), activeRule("B", RulePriority.MINOR), activeRule("C", RulePriority.MAJOR), | |||
activeRule("D", RulePriority.CRITICAL), activeRule("E", RulePriority.BLOCKER), activeRule("F", null)); | |||
mockForSingleQPInsert(); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
assertThat(callLogs) | |||
@@ -237,7 +237,7 @@ public class DefinedQProfileCreationImplTest { | |||
mockRuleActivatorActivate(callLogs, Collections.emptyList()); | |||
OrganizationDto organization = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.create(FOO_LANGUAGE, "foo1", true, | |||
activeRule("A", RulePriority.INFO, | |||
"param1", "value1", | |||
"param2", "value2", | |||
@@ -245,7 +245,7 @@ public class DefinedQProfileCreationImplTest { | |||
"param4", "value4")); | |||
mockForSingleQPInsert(); | |||
underTest.create(dbSession, definedQProfile, organization, activeRuleChanges); | |||
underTest.create(dbSession, builtInQProfile, organization, activeRuleChanges); | |||
dbSession.commit(); | |||
Set<Map.Entry<String, String>> parameters = callLogs.get(0).getRuleActivation().getParameters().entrySet(); |
@@ -30,7 +30,7 @@ import org.sonar.db.organization.OrganizationDto; | |||
import static com.google.common.base.Preconditions.checkState; | |||
public final class DefinedQProfileCreationRule extends ExternalResource implements DefinedQProfileCreation { | |||
public final class BuiltInQProfileCreationRule extends ExternalResource implements BuiltInQProfileCreation { | |||
private final List<CallLog> callLogs = new ArrayList<>(); | |||
private List<List<ActiveRuleChange>> changesPerCall = null; | |||
private Iterator<List<ActiveRuleChange>> changesPerCallIterator = null; | |||
@@ -43,7 +43,7 @@ public final class DefinedQProfileCreationRule extends ExternalResource implemen | |||
} | |||
@Override | |||
public void create(DbSession session, DefinedQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
public void create(DbSession session, BuiltInQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
callLogs.add(new CallLog(qualityProfile, organization)); | |||
if (changesPerCallIterator == null) { | |||
@@ -52,8 +52,8 @@ public final class DefinedQProfileCreationRule extends ExternalResource implemen | |||
changes.addAll(changesPerCallIterator.next()); | |||
} | |||
public DefinedQProfileCreationRule addChanges(ActiveRuleChange... changes) { | |||
checkState(changesPerCallIterator == null, "Can't add changes if DefinedQProfileCreation is in use"); | |||
public BuiltInQProfileCreationRule addChanges(ActiveRuleChange... changes) { | |||
checkState(changesPerCallIterator == null, "Can't add changes if BuiltInQProfileCreation is in use"); | |||
if (changesPerCall == null) { | |||
changesPerCall = new ArrayList<>(); | |||
} | |||
@@ -66,16 +66,16 @@ public final class DefinedQProfileCreationRule extends ExternalResource implemen | |||
} | |||
public static final class CallLog { | |||
private final DefinedQProfile definedQProfile; | |||
private final BuiltInQProfile builtInQProfile; | |||
private final OrganizationDto organizationDto; | |||
private CallLog(DefinedQProfile definedQProfile, OrganizationDto organizationDto) { | |||
this.definedQProfile = definedQProfile; | |||
private CallLog(BuiltInQProfile builtInQProfile, OrganizationDto organizationDto) { | |||
this.builtInQProfile = builtInQProfile; | |||
this.organizationDto = organizationDto; | |||
} | |||
public DefinedQProfile getDefinedQProfile() { | |||
return definedQProfile; | |||
public BuiltInQProfile getDefinedQProfile() { | |||
return builtInQProfile; | |||
} | |||
public OrganizationDto getOrganizationDto() { |
@@ -25,8 +25,8 @@ import org.junit.rules.ExternalResource; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.organization.OrganizationDto; | |||
public class DefinedQProfileInsertRule extends ExternalResource implements DefinedQProfileInsert { | |||
private final List<DefinedQProfileInsertRule.CallLog> callLogs = new ArrayList<>(); | |||
public class BuiltInQProfileInsertRule extends ExternalResource implements BuiltInQProfileInsert { | |||
private final List<BuiltInQProfileInsertRule.CallLog> callLogs = new ArrayList<>(); | |||
@Override | |||
protected void before() throws Throwable { | |||
@@ -34,25 +34,25 @@ public class DefinedQProfileInsertRule extends ExternalResource implements Defin | |||
} | |||
@Override | |||
public void create(DbSession session, DbSession batchSession, DefinedQProfile definedQProfile, OrganizationDto organization) { | |||
callLogs.add(new DefinedQProfileInsertRule.CallLog(definedQProfile, organization)); | |||
public void create(DbSession session, DbSession batchSession, BuiltInQProfile builtInQProfile, OrganizationDto organization) { | |||
callLogs.add(new BuiltInQProfileInsertRule.CallLog(builtInQProfile, organization)); | |||
} | |||
public List<DefinedQProfileInsertRule.CallLog> getCallLogs() { | |||
public List<BuiltInQProfileInsertRule.CallLog> getCallLogs() { | |||
return callLogs; | |||
} | |||
public static final class CallLog { | |||
private final DefinedQProfile definedQProfile; | |||
private final BuiltInQProfile builtInQProfile; | |||
private final OrganizationDto organizationDto; | |||
private CallLog(DefinedQProfile definedQProfile, OrganizationDto organizationDto) { | |||
this.definedQProfile = definedQProfile; | |||
private CallLog(BuiltInQProfile builtInQProfile, OrganizationDto organizationDto) { | |||
this.builtInQProfile = builtInQProfile; | |||
this.organizationDto = organizationDto; | |||
} | |||
public DefinedQProfile getDefinedQProfile() { | |||
return definedQProfile; | |||
public BuiltInQProfile getDefinedQProfile() { | |||
return builtInQProfile; | |||
} | |||
public OrganizationDto getOrganizationDto() { |
@@ -24,16 +24,16 @@ import org.junit.Test; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class DefinedQProfileLoaderTest { | |||
public class BuiltInQProfileLoaderTest { | |||
@Rule | |||
public DefinedQProfileRepositoryRule definedQProfileRepositoryRule = new DefinedQProfileRepositoryRule(); | |||
public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule(); | |||
private DefinedQProfileLoader underTest = new DefinedQProfileLoader(definedQProfileRepositoryRule); | |||
private BuiltInQProfileLoader underTest = new BuiltInQProfileLoader(builtInQProfileRepositoryRule); | |||
@Test | |||
public void start_initializes_DefinedQProfileRepository() { | |||
underTest.start(); | |||
assertThat(definedQProfileRepositoryRule.isInitialized()).isTrue(); | |||
assertThat(builtInQProfileRepositoryRule.isInitialized()).isTrue(); | |||
} | |||
} |
@@ -37,7 +37,7 @@ import org.sonar.server.language.LanguageTesting; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class DefinedQProfileRepositoryImplTest { | |||
public class BuiltInQProfileRepositoryImplTest { | |||
private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo"); | |||
private static final String SONAR_WAY_QP_NAME = "Sonar way"; | |||
@@ -46,7 +46,7 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void getQProfilesByLanguage_throws_ISE_if_called_before_initialize() { | |||
DefinedQProfileRepositoryImpl underTest = new DefinedQProfileRepositoryImpl(new Languages()); | |||
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages()); | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage("initialize must be called first"); | |||
@@ -56,7 +56,7 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_throws_ISE_if_called_twice() { | |||
DefinedQProfileRepositoryImpl underTest = new DefinedQProfileRepositoryImpl(new Languages()); | |||
BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages()); | |||
underTest.initialize(); | |||
expectedException.expect(IllegalStateException.class); | |||
@@ -67,7 +67,7 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_creates_no_DefinedQProfile_when_there_is_no_definition() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE)); | |||
underTest.initialize(); | |||
@@ -76,7 +76,7 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_creates_no_DefinedQProfile_when_all_definitions_apply_to_non_defined_languages() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(), new DummyProfileDefinition("foo", "P1", false)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), new DummyProfileDefinition("foo", "P1", false)); | |||
underTest.initialize(); | |||
@@ -86,7 +86,7 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_throws_IAE_if_profileDefinition_creates_RulesProfile_with_null_name() { | |||
DummyProfileDefinition definition = new DummyProfileDefinition("foo", null, false); | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(), definition); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), definition); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Profile created by Definition " + definition + " can't have a blank name"); | |||
@@ -97,7 +97,7 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_throws_IAE_if_profileDefinition_creates_RulesProfile_with_empty_name() { | |||
DummyProfileDefinition definition = new DummyProfileDefinition("foo", "", false); | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(), definition); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), definition); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Profile created by Definition " + definition + " can't have a blank name"); | |||
@@ -107,31 +107,31 @@ public class DefinedQProfileRepositoryImplTest { | |||
@Test | |||
public void initialize_makes_single_qp_of_a_language_default_even_if_not_flagged_as_so() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false)); | |||
underTest.initialize(); | |||
Map<String, List<DefinedQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
Map<String, List<BuiltInQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
assertThat(qProfilesByLanguage) | |||
.hasSize(1) | |||
.containsOnlyKeys(FOO_LANGUAGE.getKey()); | |||
assertThat(qProfilesByLanguage.get(FOO_LANGUAGE.getKey())) | |||
.extracting(DefinedQProfile::isDefault) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(true); | |||
} | |||
@Test | |||
public void initialize_makes_single_qp_of_a_language_default_even_if_flagged_as_so() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true)); | |||
underTest.initialize(); | |||
Map<String, List<DefinedQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
Map<String, List<BuiltInQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
assertThat(qProfilesByLanguage) | |||
.hasSize(1) | |||
.containsOnlyKeys(FOO_LANGUAGE.getKey()); | |||
assertThat(qProfilesByLanguage.get(FOO_LANGUAGE.getKey())) | |||
.extracting(DefinedQProfile::isDefault) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(true); | |||
} | |||
@@ -142,26 +142,26 @@ public class DefinedQProfileRepositoryImplTest { | |||
Collections.shuffle(definitions); | |||
String firstQPName = definitions.get(0).getName(); | |||
String secondQPName = definitions.get(1).getName(); | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), definitions.stream().toArray(ProfileDefinition[]::new)); | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), definitions.stream().toArray(ProfileDefinition[]::new)); | |||
underTest.initialize(); | |||
Map<String, List<DefinedQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
Map<String, List<BuiltInQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
assertThat(qProfilesByLanguage) | |||
.hasSize(1) | |||
.containsOnlyKeys(FOO_LANGUAGE.getKey()); | |||
List<DefinedQProfile> fooDefinedQProfiles = qProfilesByLanguage.get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::getName) | |||
List<BuiltInQProfile> fooBuiltInQProfiles = qProfilesByLanguage.get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly(firstQPName, secondQPName); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::isDefault) | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(true, false); | |||
} | |||
@Test | |||
public void initialize_fails_with_ISE_when_two_sq_with_different_name_are_default_for_the_same_language() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo2", true)); | |||
expectedException.expect(IllegalStateException.class); | |||
@@ -174,86 +174,86 @@ public class DefinedQProfileRepositoryImplTest { | |||
public void initialize_create_qp_as_default_even_if_only_one_profile_with_given_name_has_default_flag_true() { | |||
String name = "doh"; | |||
boolean flag = new Random().nextBoolean(); | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", name, flag), new DummyProfileDefinition("foo", name, !flag)); | |||
underTest.initialize(); | |||
assertThat(underTest.getQProfilesByLanguage().get(FOO_LANGUAGE.getKey())) | |||
.extracting(DefinedQProfile::isDefault) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(true); | |||
} | |||
@Test | |||
public void initialize_creates_single_qp_if_several_profile_have_the_same_name_for_a_given_language() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo1", true)); | |||
underTest.initialize(); | |||
Map<String, List<DefinedQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
Map<String, List<BuiltInQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
assertThat(qProfilesByLanguage) | |||
.hasSize(1) | |||
.containsOnlyKeys(FOO_LANGUAGE.getKey()); | |||
assertThat(qProfilesByLanguage.get(FOO_LANGUAGE.getKey())) | |||
.extracting(DefinedQProfile::getName) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly("foo1"); | |||
} | |||
@Test | |||
public void initialize_creates_qp_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl( | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl( | |||
new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "doh", false), new DummyProfileDefinition("foo", "boo", false), | |||
new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", false)); | |||
underTest.initialize(); | |||
Map<String, List<DefinedQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
Map<String, List<BuiltInQProfile>> qProfilesByLanguage = underTest.getQProfilesByLanguage(); | |||
assertThat(qProfilesByLanguage) | |||
.hasSize(1) | |||
.containsOnlyKeys(FOO_LANGUAGE.getKey()); | |||
List<DefinedQProfile> fooDefinedQProfiles = qProfilesByLanguage.get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::getName) | |||
List<BuiltInQProfile> fooBuiltInQProfiles = qProfilesByLanguage.get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly("doh", "boo", SONAR_WAY_QP_NAME, "goo"); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::isDefault) | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(false, false, true, false); | |||
} | |||
@Test | |||
public void initialize_does_not_create_Sonar_Way_as_default_if_other_profile_is_defined_as_default() { | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl( | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl( | |||
new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", true)); | |||
underTest.initialize(); | |||
List<DefinedQProfile> fooDefinedQProfiles = underTest.getQProfilesByLanguage().get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::getName) | |||
List<BuiltInQProfile> fooBuiltInQProfiles = underTest.getQProfilesByLanguage().get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly(SONAR_WAY_QP_NAME, "goo"); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::isDefault) | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(false, true); | |||
} | |||
@Test | |||
public void initialize_matches_Sonar_Way_default_with_case_sensitivity() { | |||
String sonarWayInOtherCase = SONAR_WAY_QP_NAME.toUpperCase(); | |||
DefinedQProfileRepository underTest = new DefinedQProfileRepositoryImpl( | |||
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl( | |||
new Languages(FOO_LANGUAGE), | |||
new DummyProfileDefinition("foo", "goo", false), new DummyProfileDefinition("foo", sonarWayInOtherCase, false)); | |||
underTest.initialize(); | |||
List<DefinedQProfile> fooDefinedQProfiles = underTest.getQProfilesByLanguage().get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::getName) | |||
List<BuiltInQProfile> fooBuiltInQProfiles = underTest.getQProfilesByLanguage().get(FOO_LANGUAGE.getKey()); | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::getName) | |||
.containsExactly("goo", sonarWayInOtherCase); | |||
assertThat(fooDefinedQProfiles) | |||
.extracting(DefinedQProfile::isDefault) | |||
assertThat(fooBuiltInQProfiles) | |||
.extracting(BuiltInQProfile::isDefault) | |||
.containsExactly(true, false); | |||
} | |||
@@ -34,9 +34,9 @@ import org.sonar.core.util.stream.MoreCollectors; | |||
import static com.google.common.base.Preconditions.checkState; | |||
import static org.sonar.core.util.stream.MoreCollectors.toList; | |||
public class DefinedQProfileRepositoryRule extends ExternalResource implements DefinedQProfileRepository { | |||
public class BuiltInQProfileRepositoryRule extends ExternalResource implements BuiltInQProfileRepository { | |||
private boolean initializeCalled = false; | |||
private Map<String, List<DefinedQProfile>> qProfilesbyLanguage = new HashMap<>(); | |||
private Map<String, List<BuiltInQProfile>> qProfilesbyLanguage = new HashMap<>(); | |||
@Override | |||
protected void before() throws Throwable { | |||
@@ -51,7 +51,7 @@ public class DefinedQProfileRepositoryRule extends ExternalResource implements D | |||
} | |||
@Override | |||
public Map<String, List<DefinedQProfile>> getQProfilesByLanguage() { | |||
public Map<String, List<BuiltInQProfile>> getQProfilesByLanguage() { | |||
checkState(initializeCalled, "initialize must be called first"); | |||
return ImmutableMap.copyOf(qProfilesbyLanguage); | |||
@@ -61,31 +61,31 @@ public class DefinedQProfileRepositoryRule extends ExternalResource implements D | |||
return initializeCalled; | |||
} | |||
public DefinedQProfileRepositoryRule set(String languageKey, DefinedQProfile first, DefinedQProfile... others) { | |||
public BuiltInQProfileRepositoryRule set(String languageKey, BuiltInQProfile first, BuiltInQProfile... others) { | |||
qProfilesbyLanguage.put( | |||
languageKey, | |||
Stream.concat(Stream.of(first), Arrays.stream(others)).collect(toList(1 + others.length))); | |||
return this; | |||
} | |||
public DefinedQProfile add(Language language, String profileName) { | |||
public BuiltInQProfile add(Language language, String profileName) { | |||
return add(language, profileName, false); | |||
} | |||
public DefinedQProfile add(Language language, String profileName, boolean isDefault) { | |||
DefinedQProfile definedQProfile = create(language, profileName, isDefault); | |||
public BuiltInQProfile add(Language language, String profileName, boolean isDefault) { | |||
BuiltInQProfile builtInQProfile = create(language, profileName, isDefault); | |||
qProfilesbyLanguage.compute(language.getKey(), | |||
(key, existing) -> { | |||
if (existing == null) { | |||
return ImmutableList.of(definedQProfile); | |||
return ImmutableList.of(builtInQProfile); | |||
} | |||
return Stream.concat(existing.stream(), Stream.of(definedQProfile)).collect(MoreCollectors.toList(existing.size() + 1)); | |||
return Stream.concat(existing.stream(), Stream.of(builtInQProfile)).collect(MoreCollectors.toList(existing.size() + 1)); | |||
}); | |||
return definedQProfile; | |||
return builtInQProfile; | |||
} | |||
public DefinedQProfile create(Language language, String profileName, boolean isDefault, org.sonar.api.rules.ActiveRule... rules) { | |||
return new DefinedQProfile.Builder() | |||
public BuiltInQProfile create(Language language, String profileName, boolean isDefault, org.sonar.api.rules.ActiveRule... rules) { | |||
return new BuiltInQProfile.Builder() | |||
.setLanguage(language.getKey()) | |||
.setName(profileName) | |||
.setDeclaredDefault(isDefault) |
@@ -69,7 +69,7 @@ public class QProfileFactoryMediumTest { | |||
public void checkAndCreate() { | |||
String uuid = organization.getUuid(); | |||
QualityProfileDto writtenDto = factory.checkAndCreate(dbSession, organization, new QProfileName("xoo", "P1")); | |||
QualityProfileDto writtenDto = factory.checkAndCreateCustom(dbSession, organization, new QProfileName("xoo", "P1")); | |||
dbSession.commit(); | |||
dbSession.clearCache(); | |||
assertThat(writtenDto.getOrganizationUuid()).isEqualTo(uuid); | |||
@@ -77,6 +77,7 @@ public class QProfileFactoryMediumTest { | |||
assertThat(writtenDto.getName()).isEqualTo("P1"); | |||
assertThat(writtenDto.getLanguage()).isEqualTo("xoo"); | |||
assertThat(writtenDto.getId()).isNotNull(); | |||
assertThat(writtenDto.isBuiltIn()).isFalse(); | |||
// reload the dto | |||
QualityProfileDto readDto = db.qualityProfileDao().selectByNameAndLanguage(organization, "P1", "xoo", dbSession); | |||
@@ -89,7 +90,7 @@ public class QProfileFactoryMediumTest { | |||
public void create() { | |||
String uuid = organization.getUuid(); | |||
QualityProfileDto writtenDto = factory.create(dbSession, organization, new QProfileName("xoo", "P1"), true); | |||
QualityProfileDto writtenDto = factory.createBuiltIn(dbSession, organization, new QProfileName("xoo", "P1"), true); | |||
dbSession.commit(); | |||
dbSession.clearCache(); | |||
assertThat(writtenDto.getOrganizationUuid()).isEqualTo(uuid); | |||
@@ -113,7 +114,7 @@ public class QProfileFactoryMediumTest { | |||
expectBadRequestException("quality_profiles.profile_name_cant_be_blank"); | |||
factory.checkAndCreate(dbSession, organization, name); | |||
factory.checkAndCreateCustom(dbSession, organization, name); | |||
} | |||
@Test | |||
@@ -122,19 +123,19 @@ public class QProfileFactoryMediumTest { | |||
expectBadRequestException("quality_profiles.profile_name_cant_be_blank"); | |||
factory.checkAndCreate(dbSession, organization, name); | |||
factory.checkAndCreateCustom(dbSession, organization, name); | |||
} | |||
@Test | |||
public void checkAndCreate_throws_BadRequestException_if_already_exists() { | |||
QProfileName name = new QProfileName("xoo", "P1"); | |||
factory.checkAndCreate(dbSession, organization, name); | |||
factory.checkAndCreateCustom(dbSession, organization, name); | |||
dbSession.commit(); | |||
dbSession.clearCache(); | |||
expectBadRequestException("Quality profile already exists: {lang=xoo, name=P1}"); | |||
factory.checkAndCreate(dbSession, organization, name); | |||
factory.checkAndCreateCustom(dbSession, organization, name); | |||
} | |||
@Test | |||
@@ -143,7 +144,7 @@ public class QProfileFactoryMediumTest { | |||
expectBadRequestException("quality_profiles.profile_name_cant_be_blank"); | |||
factory.create(dbSession, organization, name, true); | |||
factory.createBuiltIn(dbSession, organization, name, true); | |||
} | |||
@Test | |||
@@ -152,17 +153,17 @@ public class QProfileFactoryMediumTest { | |||
expectBadRequestException("quality_profiles.profile_name_cant_be_blank"); | |||
factory.create(dbSession, organization, name, false); | |||
factory.createBuiltIn(dbSession, organization, name, false); | |||
} | |||
@Test | |||
public void create_does_not_fail_if_already_exists() { | |||
QProfileName name = new QProfileName("xoo", "P1"); | |||
factory.create(dbSession, organization, name, true); | |||
factory.createBuiltIn(dbSession, organization, name, true); | |||
dbSession.commit(); | |||
dbSession.clearCache(); | |||
assertThat(factory.create(dbSession, organization, name, true)).isNotNull(); | |||
assertThat(factory.createBuiltIn(dbSession, organization, name, true)).isNotNull(); | |||
} | |||
private void expectBadRequestException(String message) { |
@@ -86,6 +86,7 @@ public class RegisterQualityProfilesMediumTest { | |||
assertThat(qualityProfileDao.selectAll(dbSession, organization)).hasSize(1); | |||
QualityProfileDto profile = qualityProfileDao.selectByNameAndLanguage(organization, "Basic", "xoo", dbSession); | |||
assertThat(profile).isNotNull(); | |||
assertThat(profile.isBuiltIn()).isTrue(); | |||
// Check ActiveRules in DB | |||
ActiveRuleDao activeRuleDao = dbClient.activeRuleDao(); | |||
@@ -100,6 +101,7 @@ public class RegisterQualityProfilesMediumTest { | |||
tester.get(Platform.class).restart(); | |||
assertThat(profile.isBuiltIn()).isTrue(); | |||
assertThat(activeRuleDao.selectByKey(dbSession, activeRuleKey)).isPresent(); | |||
// Check ActiveRules | |||
@@ -134,6 +136,7 @@ public class RegisterQualityProfilesMediumTest { | |||
assertThat(qualityProfileDao.selectAll(dbSession, organization)).hasSize(1); | |||
QualityProfileDto profile = qualityProfileDao.selectByNameAndLanguage(organization, "Basic", "xoo", dbSession); | |||
assertThat(profile).isNotNull(); | |||
assertThat(profile.isBuiltIn()).isTrue(); | |||
// Check Default Profile | |||
verifyDefaultProfile(organization, "xoo", "Basic"); |
@@ -32,12 +32,15 @@ import org.mockito.ArgumentCaptor; | |||
import org.sonar.api.resources.Language; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.utils.internal.AlwaysIncreasingSystem2; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.api.utils.log.LoggerLevel; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.loadedtemplate.LoadedTemplateDto; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.qualityprofile.QualityProfileDto; | |||
import org.sonar.server.language.LanguageTesting; | |||
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; | |||
import org.sonar.server.tester.UserSessionRule; | |||
@@ -59,16 +62,18 @@ public class RegisterQualityProfilesTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Rule | |||
public DefinedQProfileRepositoryRule definedQProfileRepositoryRule = new DefinedQProfileRepositoryRule(); | |||
public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule(); | |||
@Rule | |||
public LogTester logTester = new LogTester(); | |||
private DbClient dbClient = dbTester.getDbClient(); | |||
private DbClient mockedDbClient = mock(DbClient.class); | |||
private ActiveRuleIndexer mockedActiveRuleIndexer = mock(ActiveRuleIndexer.class); | |||
private DummyDefinedQProfileCreation definedQProfileCreation = new DummyDefinedQProfileCreation(); | |||
private DummyBuiltInQProfileCreation builtInQProfileCreation = new DummyBuiltInQProfileCreation(); | |||
private RegisterQualityProfiles underTest = new RegisterQualityProfiles( | |||
definedQProfileRepositoryRule, | |||
builtInQProfileRepositoryRule, | |||
dbClient, | |||
definedQProfileCreation, | |||
builtInQProfileCreation, | |||
mockedActiveRuleIndexer); | |||
@Test | |||
@@ -81,12 +86,12 @@ public class RegisterQualityProfilesTest { | |||
@Test | |||
public void no_action_in_DB_nothing_to_index_when_there_is_no_DefinedQProfile() { | |||
RegisterQualityProfiles underTest = new RegisterQualityProfiles(definedQProfileRepositoryRule, mockedDbClient, null, mockedActiveRuleIndexer); | |||
definedQProfileRepositoryRule.initialize(); | |||
RegisterQualityProfiles underTest = new RegisterQualityProfiles(builtInQProfileRepositoryRule, mockedDbClient, null, mockedActiveRuleIndexer); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.start(); | |||
assertThat(definedQProfileCreation.getCallLogs()).isEmpty(); | |||
assertThat(builtInQProfileCreation.getCallLogs()).isEmpty(); | |||
verify(mockedDbClient).openSession(false); | |||
verify(mockedActiveRuleIndexer).index(Collections.emptyList()); | |||
verifyNoMoreInteractions(mockedDbClient, mockedActiveRuleIndexer); | |||
@@ -96,46 +101,46 @@ public class RegisterQualityProfilesTest { | |||
public void start_creates_qps_for_every_organization_in_DB_when_LoadedTemplate_table_is_empty() { | |||
OrganizationDto organization1 = dbTester.organizations().insert(); | |||
OrganizationDto organization2 = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.add(FOO_LANGUAGE, "foo1"); | |||
definedQProfileRepositoryRule.initialize(); | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.add(FOO_LANGUAGE, "foo1"); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.start(); | |||
assertThat(definedQProfileCreation.getCallLogs()) | |||
assertThat(builtInQProfileCreation.getCallLogs()) | |||
.containsExactly( | |||
callLog(definedQProfile, dbTester.getDefaultOrganization()), | |||
callLog(definedQProfile, organization1), | |||
callLog(definedQProfile, organization2)); | |||
callLog(builtInQProfile, dbTester.getDefaultOrganization()), | |||
callLog(builtInQProfile, organization1), | |||
callLog(builtInQProfile, organization2)); | |||
} | |||
@Test | |||
public void start_creates_qps_only_for_organizations_in_DB_without_loaded_template() { | |||
OrganizationDto org1 = dbTester.organizations().insert(); | |||
OrganizationDto org2 = dbTester.organizations().insert(); | |||
DefinedQProfile definedQProfile = definedQProfileRepositoryRule.add(FOO_LANGUAGE, "foo1"); | |||
dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(dbTester.getDefaultOrganization().getUuid(), definedQProfile.getLoadedTemplateType()), dbTester.getSession()); | |||
dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(org1.getUuid(), definedQProfile.getLoadedTemplateType()), dbTester.getSession()); | |||
BuiltInQProfile builtInQProfile = builtInQProfileRepositoryRule.add(FOO_LANGUAGE, "foo1"); | |||
dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(dbTester.getDefaultOrganization().getUuid(), builtInQProfile.getLoadedTemplateType()), dbTester.getSession()); | |||
dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(org1.getUuid(), builtInQProfile.getLoadedTemplateType()), dbTester.getSession()); | |||
dbTester.commit(); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.start(); | |||
assertThat(definedQProfileCreation.getCallLogs()) | |||
.containsExactly(callLog(definedQProfile, org2)); | |||
assertThat(builtInQProfileCreation.getCallLogs()) | |||
.containsExactly(callLog(builtInQProfile, org2)); | |||
} | |||
@Test | |||
public void start_creates_different_qps_and_their_loaded_templates_if_several_profile_has_same_name_for_different_languages() { | |||
String name = "doh"; | |||
DefinedQProfile definedQProfile1 = definedQProfileRepositoryRule.add(FOO_LANGUAGE, name, true); | |||
DefinedQProfile definedQProfile2 = definedQProfileRepositoryRule.add(BAR_LANGUAGE, name, true); | |||
definedQProfileRepositoryRule.initialize(); | |||
BuiltInQProfile builtInQProfile1 = builtInQProfileRepositoryRule.add(FOO_LANGUAGE, name, true); | |||
BuiltInQProfile builtInQProfile2 = builtInQProfileRepositoryRule.add(BAR_LANGUAGE, name, true); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.start(); | |||
assertThat(definedQProfileCreation.getCallLogs()) | |||
.containsExactly(callLog(definedQProfile2, dbTester.getDefaultOrganization()), callLog(definedQProfile1, dbTester.getDefaultOrganization())); | |||
assertThat(builtInQProfileCreation.getCallLogs()) | |||
.containsExactly(callLog(builtInQProfile2, dbTester.getDefaultOrganization()), callLog(builtInQProfile1, dbTester.getDefaultOrganization())); | |||
} | |||
@Test | |||
@@ -143,17 +148,17 @@ public class RegisterQualityProfilesTest { | |||
dbTester.organizations().insert(); | |||
dbTester.organizations().insert(); | |||
dbTester.organizations().insert(); | |||
definedQProfileRepositoryRule.add(FOO_LANGUAGE, "foo1", false); | |||
definedQProfileRepositoryRule.initialize(); | |||
builtInQProfileRepositoryRule.add(FOO_LANGUAGE, "foo1", false); | |||
builtInQProfileRepositoryRule.initialize(); | |||
ActiveRuleChange ruleChange1 = newActiveRuleChange("1"); | |||
ActiveRuleChange ruleChange2 = newActiveRuleChange("2"); | |||
ActiveRuleChange ruleChange3 = newActiveRuleChange("3"); | |||
ActiveRuleChange ruleChange4 = newActiveRuleChange("4"); | |||
definedQProfileCreation.addChangesPerCall(ruleChange1, ruleChange3); | |||
builtInQProfileCreation.addChangesPerCall(ruleChange1, ruleChange3); | |||
// no change for second org | |||
definedQProfileCreation.addChangesPerCall(); | |||
definedQProfileCreation.addChangesPerCall(ruleChange2); | |||
definedQProfileCreation.addChangesPerCall(ruleChange4); | |||
builtInQProfileCreation.addChangesPerCall(); | |||
builtInQProfileCreation.addChangesPerCall(ruleChange2); | |||
builtInQProfileCreation.addChangesPerCall(ruleChange4); | |||
ArgumentCaptor<List<ActiveRuleChange>> indexedChangesCaptor = ArgumentCaptor.forClass((Class<List<ActiveRuleChange>>) (Object) List.class); | |||
doNothing().when(mockedActiveRuleIndexer).index(indexedChangesCaptor.capture()); | |||
@@ -163,20 +168,37 @@ public class RegisterQualityProfilesTest { | |||
.containsExactly(ruleChange1, ruleChange3, ruleChange2, ruleChange4); | |||
} | |||
@Test | |||
public void rename_custom_outdated_profiles_if_same_name_than_builtin_profile() { | |||
OrganizationDto org1 = dbTester.organizations().insert(org -> org.setKey("org1")); | |||
OrganizationDto org2 = dbTester.organizations().insert(org -> org.setKey("org2")); | |||
QualityProfileDto outdatedProfileInOrg1 = dbTester.qualityProfiles().insert(org1, p -> p.setIsBuiltIn(false).setLanguage(FOO_LANGUAGE.getKey()).setName("Sonar way")); | |||
QualityProfileDto outdatedProfileInOrg2 = dbTester.qualityProfiles().insert(org2, p -> p.setIsBuiltIn(false).setLanguage(FOO_LANGUAGE.getKey()).setName("Sonar way")); | |||
builtInQProfileRepositoryRule.add(FOO_LANGUAGE, "Sonar way", false); | |||
builtInQProfileRepositoryRule.initialize(); | |||
underTest.start(); | |||
assertThat(dbTester.qualityProfiles().selectByKey(outdatedProfileInOrg1.getKey()).get().getName()).isEqualTo("Sonar way (outdated copy)"); | |||
assertThat(dbTester.qualityProfiles().selectByKey(outdatedProfileInOrg2.getKey()).get().getName()).isEqualTo("Sonar way (outdated copy)"); | |||
assertThat(logTester.logs(LoggerLevel.INFO)).contains("Rename Quality profiles [foo/Sonar way] to [Sonar way (outdated copy)] in 2 organizations"); | |||
} | |||
private static ActiveRuleChange newActiveRuleChange(String id) { | |||
return ActiveRuleChange.createFor(ActiveRuleChange.Type.ACTIVATED, ActiveRuleKey.of(id, RuleKey.of(id + "1", id + "2"))); | |||
} | |||
private class DummyDefinedQProfileCreation implements DefinedQProfileCreation { | |||
private class DummyBuiltInQProfileCreation implements BuiltInQProfileCreation { | |||
private List<List<ActiveRuleChange>> changesPerCall; | |||
private Iterator<List<ActiveRuleChange>> changesPerCallIterator; | |||
private final List<CallLog> callLogs = new ArrayList<>(); | |||
@Override | |||
public void create(DbSession session, DefinedQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
public void create(DbSession session, BuiltInQProfile qualityProfile, OrganizationDto organization, List<ActiveRuleChange> changes) { | |||
callLogs.add(callLog(qualityProfile, organization)); | |||
// RegisterQualityProfiles relies on the fact that DefinedQProfileCreation populates table LOADED_TEMPLATE each time create is called | |||
// RegisterQualityProfiles relies on the fact that BuiltInQProfileCreation populates table LOADED_TEMPLATE each time create is called | |||
// to not loop infinitely | |||
dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(organization.getUuid(), qualityProfile.getLoadedTemplateType()), session); | |||
@@ -201,11 +223,11 @@ public class RegisterQualityProfilesTest { | |||
} | |||
private static final class CallLog { | |||
private final DefinedQProfile definedQProfile; | |||
private final BuiltInQProfile builtInQProfile; | |||
private final OrganizationDto organization; | |||
private CallLog(DefinedQProfile definedQProfile, OrganizationDto organization) { | |||
this.definedQProfile = definedQProfile; | |||
private CallLog(BuiltInQProfile builtInQProfile, OrganizationDto organization) { | |||
this.builtInQProfile = builtInQProfile; | |||
this.organization = organization; | |||
} | |||
@@ -218,25 +240,25 @@ public class RegisterQualityProfilesTest { | |||
return false; | |||
} | |||
CallLog callLog = (CallLog) o; | |||
return definedQProfile == callLog.definedQProfile && | |||
return builtInQProfile == callLog.builtInQProfile && | |||
organization.getUuid().equals(callLog.organization.getUuid()); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(definedQProfile, organization); | |||
return Objects.hash(builtInQProfile, organization); | |||
} | |||
@Override | |||
public String toString() { | |||
return "CallLog{" + | |||
"qp=" + definedQProfile.getLanguage() + '-' + definedQProfile.getName() + '-' + definedQProfile.isDefault() + | |||
"qp=" + builtInQProfile.getLanguage() + '-' + builtInQProfile.getName() + '-' + builtInQProfile.isDefault() + | |||
", org=" + organization.getKey() + | |||
'}'; | |||
} | |||
} | |||
private static CallLog callLog(DefinedQProfile definedQProfile, OrganizationDto organizationDto) { | |||
return new CallLog(definedQProfile, organizationDto); | |||
private static CallLog callLog(BuiltInQProfile builtInQProfile, OrganizationDto organizationDto) { | |||
return new CallLog(builtInQProfile, organizationDto); | |||
} | |||
} |
@@ -22,6 +22,7 @@ | |||
kee="sonar-way" | |||
language="xoo" | |||
parent_kee="[null]" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<active_rules id="1" |
@@ -22,6 +22,7 @@ | |||
kee="parent" | |||
language="xoo" | |||
parent_kee="[null]" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<rules_profiles id="2" | |||
@@ -30,6 +31,7 @@ | |||
kee="child" | |||
language="xoo" | |||
parent_kee="parent" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<active_rules id="1" |
@@ -22,6 +22,7 @@ | |||
kee="parent" | |||
language="xoo" | |||
parent_kee="[null]" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<rules_profiles id="2" | |||
@@ -30,6 +31,7 @@ | |||
kee="child" | |||
language="xoo" | |||
parent_kee="parent" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<active_rules id="1" |
@@ -22,6 +22,7 @@ | |||
kee="sonar-way" | |||
language="xoo" | |||
parent_kee="[null]" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<active_rules id="1" |
@@ -38,6 +38,7 @@ | |||
kee="parent" | |||
language="xoo" | |||
parent_kee="[null]" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<rules_profiles id="2" | |||
@@ -46,6 +47,7 @@ | |||
kee="child" | |||
language="xoo" | |||
parent_kee="parent" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<active_rules id="1" | |||
@@ -71,6 +73,7 @@ | |||
kee="sonar-way" | |||
language="xoo" | |||
parent_kee="[null]" | |||
is_built_in="[false]" | |||
is_default="[false]"/> | |||
<active_rules id="3" |