public class RuleDao implements Dao {
+ public Optional<RuleDto> selectByKey(DbSession session, OrganizationDto organization, RuleKey key) {
+ return selectByKey(session, organization.getUuid(), key);
+ }
+
+ /**
+ * @deprecated use {@link #selectByKey(DbSession, OrganizationDto, RuleKey)}
+ */
+ @Deprecated
public Optional<RuleDto> selectByKey(DbSession session, String organizationUuid, RuleKey key) {
RuleDto res = mapper(session).selectByKey(organizationUuid, key);
ensureOrganizationIsSet(organizationUuid, res);
return java.util.Optional.ofNullable(mapper(session).selectMetadataByKey(key, organization.getUuid()));
}
- public RuleDto selectOrFailByKey(DbSession session, String organizationUuid, RuleKey key) {
- RuleDto rule = mapper(session).selectByKey(organizationUuid, key);
+ public RuleDto selectOrFailByKey(DbSession session, OrganizationDto organization, RuleKey key) {
+ RuleDto rule = mapper(session).selectByKey(organization.getUuid(), key);
if (rule == null) {
throw new RowNotFoundException(String.format("Rule with key '%s' does not exist", key));
}
- ensureOrganizationIsSet(organizationUuid, rule);
+ ensureOrganizationIsSet(organization.getUuid(), rule);
return rule;
}
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
import org.sonar.db.RowNotFoundException;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.organization.OrganizationTesting;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
public void selectOrFailByKey() {
dbTester.prepareDbUnit(getClass(), "shared.xml");
- RuleDto rule = underTest.selectOrFailByKey(dbTester.getSession(), "org-1", RuleKey.of("java", "S001"));
+ OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid("org-1");
+ RuleDto rule = underTest.selectOrFailByKey(dbTester.getSession(), organization, RuleKey.of("java", "S001"));
assertThat(rule.getId()).isEqualTo(1);
}
thrown.expect(RowNotFoundException.class);
thrown.expectMessage("Rule with key 'NOT:FOUND' does not exist");
- underTest.selectOrFailByKey(dbTester.getSession(), "org-1", RuleKey.of("NOT", "FOUND"));
+ OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid("org-1");
+ underTest.selectOrFailByKey(dbTester.getSession(), organization, RuleKey.of("NOT", "FOUND"));
}
@Test
dbTester.prepareDbUnit(getClass(), "shared.xml");
String organizationUuid = "org-1";
- assertThat(underTest.selectOrFailByKey(dbTester.getSession(), organizationUuid, RuleKey.of("java", "S001")).getOrganizationUuid())
+ OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid(organizationUuid);
+ assertThat(underTest.selectOrFailByKey(dbTester.getSession(), organization, RuleKey.of("java", "S001")).getOrganizationUuid())
.isEqualTo(organizationUuid);
}
underTest.insertOrUpdate(dbTester.getSession(), metadataToUpdate);
dbTester.getSession().commit();
- RuleDto ruleDto = underTest.selectOrFailByKey(dbTester.getSession(), organizationUuid, RuleKey.of("checkstyle", "AvoidNull"));
+ OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid(organizationUuid);
+ RuleDto ruleDto = underTest.selectOrFailByKey(dbTester.getSession(), organization, RuleKey.of("checkstyle", "AvoidNull"));
assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
assertThat(ruleDto.getDescriptionFormat()).isNull();
public void update_RuleMetadataDto_updates_row_in_RULE_METADATA_if_already_exists() {
dbTester.prepareDbUnit(getClass(), "update.xml");
String organizationUuid = "org-1";
+ OrganizationDto organization = OrganizationTesting.newOrganizationDto().setUuid(organizationUuid);
RuleMetadataDto metadataV1 = new RuleMetadataDto()
.setRuleId(1)
.setOrganizationUuid(organizationUuid)
dbTester.commit();
assertThat(dbTester.countRowsOfTable("RULES_METADATA")).isEqualTo(1);
- RuleDto ruleDto = underTest.selectOrFailByKey(dbTester.getSession(), organizationUuid, RuleKey.of("checkstyle", "AvoidNull"));
+ RuleDto ruleDto = underTest.selectOrFailByKey(dbTester.getSession(), organization, RuleKey.of("checkstyle", "AvoidNull"));
assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
assertThat(ruleDto.getDescriptionFormat()).isNull();
underTest.insertOrUpdate(dbTester.getSession(), metadataV2);
dbTester.commit();
- ruleDto = underTest.selectOrFailByKey(dbTester.getSession(), organizationUuid, RuleKey.of("checkstyle", "AvoidNull"));
+ ruleDto = underTest.selectOrFailByKey(dbTester.getSession(), organization, RuleKey.of("checkstyle", "AvoidNull"));
assertThat(ruleDto.getName()).isEqualTo("Avoid Null");
assertThat(ruleDto.getDescription()).isEqualTo("Should avoid NULL");
assertThat(ruleDto.getDescriptionFormat()).isNull();
String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid();
OrganizationDto defaultOrganization = dbClient.organizationDao().selectByUuid(dbSession, defaultOrganizationUuid)
.orElseThrow(() -> new IllegalStateException(String.format("Could not find default organization for uuid '%s'", defaultOrganizationUuid)));
- RuleDto templateRule = dbClient.ruleDao().selectOrFailByKey(dbSession, defaultOrganization.getUuid(), templateKey);
+ RuleDto templateRule = dbClient.ruleDao().selectOrFailByKey(dbSession, defaultOrganization, templateKey);
if (!templateRule.isTemplate()) {
throw new IllegalArgumentException("This rule is not a template rule: " + templateKey.toString());
}
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.db.organization.OrganizationDto;
+
+import static org.sonar.server.rule.RuleUpdate.RuleUpdateUseCase.CUSTOM_RULE;
+import static org.sonar.server.rule.RuleUpdate.RuleUpdateUseCase.PLUGIN_RULE;
public class RuleUpdate {
private boolean changeSeverity = false;
private boolean changeStatus = false;
private boolean changeParameters = false;
- private boolean isCustomRule;
+ private final RuleUpdateUseCase useCase;
private Set<String> tags;
private String markdownNote;
private DebtRemediationFunction debtRemediationFunction;
private String severity;
private RuleStatus status;
private final Map<String, String> parameters = Maps.newHashMap();
+ private OrganizationDto organization;
- private RuleUpdate(RuleKey ruleKey) {
+ private RuleUpdate(RuleKey ruleKey, RuleUpdateUseCase useCase) {
this.ruleKey = ruleKey;
+ this.useCase = useCase;
}
public RuleKey getRuleKey() {
return this;
}
+ public RuleUpdate setOrganization(OrganizationDto organization) {
+ this.organization = organization;
+ return this;
+ }
+
public Map<String, String> getParameters() {
return parameters;
}
}
boolean isCustomRule() {
- return isCustomRule;
+ return useCase.isCustomRule;
}
public boolean isChangeTags() {
}
private void checkCustomRule() {
- if (!isCustomRule) {
+ if (useCase != CUSTOM_RULE) {
throw new IllegalStateException("Not a custom rule");
}
}
+ public OrganizationDto getOrganization() {
+ return organization;
+ }
+
/**
* Use to update a rule provided by a plugin (name, description, severity, status and parameters cannot by changed)
*/
public static RuleUpdate createForPluginRule(RuleKey ruleKey) {
- RuleUpdate ruleUpdate = new RuleUpdate(ruleKey);
- ruleUpdate.isCustomRule = false;
- return ruleUpdate;
+ return new RuleUpdate(ruleKey, PLUGIN_RULE);
}
/**
* Use to update a custom rule
*/
public static RuleUpdate createForCustomRule(RuleKey ruleKey) {
- RuleUpdate ruleUpdate = new RuleUpdate(ruleKey);
- ruleUpdate.isCustomRule = true;
- return ruleUpdate;
+ return new RuleUpdate(ruleKey, CUSTOM_RULE);
}
+ public enum RuleUpdateUseCase {
+ PLUGIN_RULE(false),
+ CUSTOM_RULE(true);
+
+ public final boolean isCustomRule;
+
+ RuleUpdateUseCase(boolean isCustomRule) {
+ this.isCustomRule = isCustomRule;
+ }
+ }
}
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import org.apache.commons.lang.builder.EqualsBuilder;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
import org.sonar.db.rule.RuleDefinitionDto;
/**
* Update manual rules and custom rules (rules instantiated from templates)
*/
- public boolean update(RuleUpdate update, UserSession userSession) {
- if (update.isEmpty()) {
- return false;
- }
-
- try (DbSession dbSession = dbClient.openSession(false)) {
- return update(dbSession, update, userSession);
- }
- }
-
- /**
- * Update manual rules and custom rules (rules instantiated from templates)
- */
- public boolean update(DbSession dbSession, RuleUpdate update, UserSession userSession) {
+ public boolean update(DbSession dbSession, RuleUpdate update, OrganizationDto organization, UserSession userSession) {
if (update.isEmpty()) {
return false;
}
updateParameters(dbSession, update, rule);
dbSession.commit();
- ruleIndexer.indexRuleDefinition(rule.getKey());
+ RuleKey ruleKey = rule.getKey();
+ ruleIndexer.indexRuleDefinition(ruleKey);
+ ruleIndexer.indexRuleExtension(organization, ruleKey);
return true;
}
*/
private RuleDto getRuleDto(RuleUpdate change) {
try (DbSession dbSession = dbClient.openSession(false)) {
- RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbSession, defaultOrganizationProvider.get().getUuid(), change.getRuleKey());
+ RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbSession, change.getOrganization(), change.getRuleKey());
if (RuleStatus.REMOVED == rule.getStatus()) {
throw new IllegalArgumentException("Rule with REMOVED status cannot be updated: " + change.getRuleKey());
}
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
-import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.rule.NewCustomRule;
import org.sonar.server.rule.ReactivationException;
import org.sonar.server.rule.RuleCreator;
private final DbClient dbClient;
private final RuleCreator ruleCreator;
private final RuleMapper ruleMapper;
- private final DefaultOrganizationProvider defaultOrganizationProvider;
- public CreateAction(DbClient dbClient, RuleCreator ruleCreator, RuleMapper ruleMapper, DefaultOrganizationProvider defaultOrganizationProvider) {
+ public CreateAction(DbClient dbClient, RuleCreator ruleCreator, RuleMapper ruleMapper) {
this.dbClient = dbClient;
this.ruleCreator = ruleCreator;
this.ruleMapper = ruleMapper;
- this.defaultOrganizationProvider = defaultOrganizationProvider;
}
@Override
}
writeResponse(dbSession, request, response, ruleCreator.create(dbSession, newRule));
} catch (ReactivationException e) {
- write409(dbSession, request, response, e.ruleKey());
+ response.stream().setStatus(HTTP_CONFLICT);
+ writeResponse(dbSession, request, response, e.ruleKey());
}
}
}
writeProtobuf(createResponse(dbSession, ruleKey), request, response);
}
- private void write409(DbSession dbSession, Request request, Response response, RuleKey ruleKey) {
- response.stream().setStatus(HTTP_CONFLICT);
- writeProtobuf(createResponse(dbSession, ruleKey), request, response);
- }
-
private Rules.CreateResponse createResponse(DbSession dbSession, RuleKey ruleKey) {
- String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid();
- RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbSession, defaultOrganizationUuid, ruleKey);
+ RuleDefinitionDto rule = dbClient.ruleDao().selectDefinitionByKey(dbSession, ruleKey)
+ .transform(java.util.Optional::of).or(java.util.Optional::empty)
+ .orElseThrow(() -> new IllegalStateException(String.format("Cannot load rule, that has just been created '%s'", ruleKey)));
List<RuleDefinitionDto> templateRules = new ArrayList<>();
if (rule.getTemplateId() != null) {
Optional<RuleDefinitionDto> templateRule = dbClient.ruleDao().selectDefinitionById(rule.getTemplateId(), dbSession);
}
List<RuleParamDto> ruleParameters = dbClient.ruleDao().selectRuleParamsByRuleIds(dbSession, singletonList(rule.getId()));
SearchAction.SearchResult searchResult = new SearchAction.SearchResult()
- .setRules(singletonList(rule))
.setRuleParameters(ruleParameters)
.setTemplateRules(templateRules)
.setTotal(1L);
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
import org.sonar.db.rule.RuleDefinitionDto;
-import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleMetadataDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.markdown.Markdown;
import org.sonar.server.rule.ws.SearchAction.SearchResult;
this.macroInterpreter = macroInterpreter;
}
- /**
- * Convert a RuleDto to WsRule. If fieldsToReturn is empty all the fields are returned
- */
- public Rules.Rule toWsRule(RuleDto ruleDto, SearchResult result, Set<String> fieldsToReturn) {
+ public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn) {
Rules.Rule.Builder ruleResponse = Rules.Rule.newBuilder();
+ applyRuleDefinition(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
+ return ruleResponse.build();
+ }
+
+ public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn, RuleMetadataDto metadata) {
+ Rules.Rule.Builder ruleResponse = Rules.Rule.newBuilder();
+ applyRuleDefinition(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
+ applyRuleMetadata(ruleResponse, metadata, fieldsToReturn);
+ setDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, metadata, fieldsToReturn);
+ return ruleResponse.build();
+ }
+
+ public Rules.Rule.Builder applyRuleDefinition(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn) {
// Mandatory fields
- ruleResponse.setKey(ruleDto.getKey().toString());
- Common.RuleType type = Common.RuleType.valueOf(ruleDto.getType());
- ruleResponse.setType(type);
+ ruleResponse.setKey(ruleDefinitionDto.getKey().toString());
+ ruleResponse.setType(Common.RuleType.valueOf(ruleDefinitionDto.getType()));
// Optional fields
- setRepository(ruleResponse, ruleDto, fieldsToReturn);
- setName(ruleResponse, ruleDto, fieldsToReturn);
- setStatus(ruleResponse, ruleDto, fieldsToReturn);
- setTags(ruleResponse, ruleDto, fieldsToReturn);
- setSysTags(ruleResponse, ruleDto, fieldsToReturn);
- setParams(ruleResponse, ruleDto, result, fieldsToReturn);
- setCreatedAt(ruleResponse, ruleDto, fieldsToReturn);
- setDescriptionFields(ruleResponse, ruleDto, fieldsToReturn);
- setNotesFields(ruleResponse, ruleDto, fieldsToReturn);
- setSeverity(ruleResponse, ruleDto, fieldsToReturn);
- setInternalKey(ruleResponse, ruleDto, fieldsToReturn);
- setLanguage(ruleResponse, ruleDto, fieldsToReturn);
- setLanguageName(ruleResponse, ruleDto, fieldsToReturn);
- setIsTemplate(ruleResponse, ruleDto, fieldsToReturn);
- setTemplateKey(ruleResponse, ruleDto, result, fieldsToReturn);
- setDebtRemediationFunctionFields(ruleResponse, ruleDto, fieldsToReturn);
- setDefaultDebtRemediationFunctionFields(ruleResponse, ruleDto, fieldsToReturn);
- setIsRemediationFunctionOverloaded(ruleResponse, ruleDto, fieldsToReturn);
- setEffortToFixDescription(ruleResponse, ruleDto, fieldsToReturn);
+ setRepository(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setName(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setStatus(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setSysTags(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setParams(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
+ setCreatedAt(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setDescriptionFields(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setSeverity(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setInternalKey(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setLanguage(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setLanguageName(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setIsTemplate(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setTemplateKey(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
+ setDefaultDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setEffortToFixDescription(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ return ruleResponse;
+ }
- return ruleResponse.build();
+ private void applyRuleMetadata(Rules.Rule.Builder ruleResponse, RuleMetadataDto metadata, Set<String> fieldsToReturn) {
+ setTags(ruleResponse, metadata, fieldsToReturn);
+ setNotesFields(ruleResponse, metadata, fieldsToReturn);
+ setIsRemediationFunctionOverloaded(ruleResponse, metadata, fieldsToReturn);
}
- private static void setRepository(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setRepository(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_REPO)) {
ruleResponse.setRepo(ruleDto.getKey().repository());
}
}
- private static void setEffortToFixDescription(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setEffortToFixDescription(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if ((shouldReturnField(fieldsToReturn, FIELD_EFFORT_TO_FIX_DESCRIPTION) || shouldReturnField(fieldsToReturn, FIELD_GAP_DESCRIPTION))
&& ruleDto.getGapDescription() != null) {
ruleResponse.setEffortToFixDescription(ruleDto.getGapDescription());
}
}
- private static void setIsRemediationFunctionOverloaded(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setIsRemediationFunctionOverloaded(Rules.Rule.Builder ruleResponse, RuleMetadataDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_DEBT_OVERLOADED) || shouldReturnField(fieldsToReturn, FIELD_REM_FUNCTION_OVERLOADED)) {
ruleResponse.setDebtOverloaded(isRemediationFunctionOverloaded(ruleDto));
ruleResponse.setRemFnOverloaded(isRemediationFunctionOverloaded(ruleDto));
}
}
- private static void setDefaultDebtRemediationFunctionFields(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setDefaultDebtRemediationFunctionFields(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_DEFAULT_DEBT_REM_FUNCTION) || shouldReturnField(fieldsToReturn, FIELD_DEFAULT_REM_FUNCTION)) {
DebtRemediationFunction defaultDebtRemediationFunction = defaultDebtRemediationFunction(ruleDto);
if (defaultDebtRemediationFunction != null) {
}
}
- private static void setDebtRemediationFunctionFields(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setDebtRemediationFunctionFields(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinitionDto, RuleMetadataDto ruleMetadataDto,
+ Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_DEBT_REM_FUNCTION) || shouldReturnField(fieldsToReturn, FIELD_REM_FUNCTION)) {
- DebtRemediationFunction debtRemediationFunction = debtRemediationFunction(ruleDto);
+ DebtRemediationFunction debtRemediationFunction = debtRemediationFunction(ruleDefinitionDto, ruleMetadataDto);
if (debtRemediationFunction != null) {
if (debtRemediationFunction.type() != null) {
ruleResponse.setRemFnType(debtRemediationFunction.type().name());
}
}
- private static void setName(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setName(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_NAME) && ruleDto.getName() != null) {
ruleResponse.setName(ruleDto.getName());
}
}
- private static void setStatus(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setStatus(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_STATUS) && ruleDto.getStatus() != null) {
ruleResponse.setStatus(Common.RuleStatus.valueOf(ruleDto.getStatus().toString()));
}
}
- private static void setTags(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setTags(Rules.Rule.Builder ruleResponse, RuleMetadataDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_TAGS)) {
ruleResponse.getTagsBuilder().addAllTags(ruleDto.getTags());
}
}
- private static void setSysTags(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setSysTags(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_SYSTEM_TAGS)) {
ruleResponse.getSysTagsBuilder().addAllSysTags(ruleDto.getSystemTags());
}
}
- private static void setParams(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, SearchResult searchResult, Set<String> fieldsToReturn) {
+ private static void setParams(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, SearchResult searchResult, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_PARAMS)) {
List<RuleParamDto> ruleParameters = searchResult.getRuleParamsByRuleId().get(ruleDto.getId());
ruleResponse.getParamsBuilder().addAllParams(FluentIterable.from(ruleParameters)
}
}
- private static void setCreatedAt(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setCreatedAt(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_CREATED_AT)) {
ruleResponse.setCreatedAt(formatDateTime(ruleDto.getCreatedAt()));
}
}
- private void setDescriptionFields(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private void setDescriptionFields(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_HTML_DESCRIPTION)) {
String description = ruleDto.getDescription();
if (description != null) {
}
}
- private void setNotesFields(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private void setNotesFields(Rules.Rule.Builder ruleResponse, RuleMetadataDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, "htmlNote") && ruleDto.getNoteData() != null) {
ruleResponse.setHtmlNote(macroInterpreter.interpret(Markdown.convertToHtml(ruleDto.getNoteData())));
}
}
}
- private static void setSeverity(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setSeverity(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_SEVERITY) && ruleDto.getSeverityString() != null) {
ruleResponse.setSeverity(ruleDto.getSeverityString());
}
}
- private static void setInternalKey(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setInternalKey(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_INTERNAL_KEY) && ruleDto.getConfigKey() != null) {
ruleResponse.setInternalKey(ruleDto.getConfigKey());
}
}
- private static void setLanguage(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setLanguage(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_LANGUAGE) && ruleDto.getLanguage() != null) {
ruleResponse.setLang(ruleDto.getLanguage());
}
}
- private void setLanguageName(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private void setLanguageName(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_LANGUAGE_NAME) && ruleDto.getLanguage() != null) {
String languageKey = ruleDto.getLanguage();
Language language = languages.get(languageKey);
}
}
- private static void setIsTemplate(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
+ private static void setIsTemplate(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_IS_TEMPLATE)) {
ruleResponse.setIsTemplate(ruleDto.isTemplate());
}
}
- private static void setTemplateKey(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, SearchResult result, Set<String> fieldsToReturn) {
+ private static void setTemplateKey(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, SearchResult result, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_TEMPLATE_KEY) && ruleDto.getTemplateId() != null) {
RuleDefinitionDto templateRule = result.getTemplateRulesByRuleId().get(ruleDto.getTemplateId());
if (templateRule != null) {
return fieldsToReturn.isEmpty() || fieldsToReturn.contains(fieldName);
}
- private static boolean isRemediationFunctionOverloaded(RuleDto rule) {
+ private static boolean isRemediationFunctionOverloaded(RuleMetadataDto rule) {
return rule.getRemediationFunction() != null;
}
@CheckForNull
- private static DebtRemediationFunction defaultDebtRemediationFunction(final RuleDto ruleDto) {
+ private static DebtRemediationFunction defaultDebtRemediationFunction(final RuleDefinitionDto ruleDto) {
final String function = ruleDto.getDefRemediationFunction();
if (function == null || function.isEmpty()) {
return null;
}
@CheckForNull
- private static DebtRemediationFunction debtRemediationFunction(final RuleDto ruleDto) {
- final String function = ruleDto.getRemediationFunction();
+ private static DebtRemediationFunction debtRemediationFunction(RuleDefinitionDto ruleDefinitionDto, RuleMetadataDto ruleMetadataDto) {
+ final String function = ruleMetadataDto.getRemediationFunction();
if (function == null || function.isEmpty()) {
- return defaultDebtRemediationFunction(ruleDto);
+ return defaultDebtRemediationFunction(ruleDefinitionDto);
} else {
return new DefaultDebtRemediationFunction(
DebtRemediationFunction.Type.valueOf(function.toUpperCase(Locale.ENGLISH)),
- ruleDto.getRemediationGapMultiplier(),
- ruleDto.getRemediationBaseEffort());
+ ruleMetadataDto.getRemediationGapMultiplier(),
+ ruleMetadataDto.getRemediationBaseEffort());
}
}
private void writeRules(SearchResponse.Builder response, SearchResult result, SearchOptions context) {
for (RuleDto rule : result.rules) {
- response.addRules(mapper.toWsRule(rule, result, context.getFields()));
+ response.addRules(mapper.toWsRule(rule.getDefinition(), result, context.getFields(), rule.getMetadata()));
}
}
private ShowResponse buildResponse(DbSession dbSession, Request request, SearchAction.SearchResult searchResult) {
ShowResponse.Builder responseBuilder = ShowResponse.newBuilder();
RuleDto rule = searchResult.getRules().get(0);
- responseBuilder.setRule(mapper.toWsRule(rule, searchResult, Collections.emptySet()));
+ responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata()));
if (request.mandatoryParamAsBoolean(PARAM_ACTIVES)) {
activeRuleCompleter.completeShow(dbSession, rule, responseBuilder);
*/
package org.sonar.server.rule.ws;
-import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.rule.RuleUpdate;
import org.sonar.server.rule.RuleUpdater;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Rules.UpdateResponse;
+import static java.lang.String.format;
import static java.util.Collections.singletonList;
+import static java.util.Optional.ofNullable;
import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
-import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
public class UpdateAction implements RulesWsAction {
public static final String PARAM_DESCRIPTION = "markdown_description";
public static final String PARAM_SEVERITY = "severity";
public static final String PARAM_STATUS = "status";
+ public static final String PARAM_ORGANIZATION = "organization";
public static final String PARAMS = "params";
private final DbClient dbClient;
private final DefaultOrganizationProvider defaultOrganizationProvider;
public UpdateAction(DbClient dbClient, RuleUpdater ruleUpdater, RuleMapper mapper, UserSession userSession,
- RuleWsSupport ruleWsSupport, DefaultOrganizationProvider defaultOrganizationProvider) {
+ RuleWsSupport ruleWsSupport, DefaultOrganizationProvider defaultOrganizationProvider) {
this.dbClient = dbClient;
this.ruleUpdater = ruleUpdater;
this.mapper = mapper;
.setDescription("Rule status (Only when updating a custom rule)")
.setPossibleValues(RuleStatus.values());
+ action.createParam(PARAM_ORGANIZATION)
+ .setDescription("Organization key")
+ .setRequired(false)
+ .setInternal(true)
+ .setExampleValue("my-org")
+ .setSince("6.4");
+
action.createParam(PARAMS)
.setDescription("Parameters as semi-colon list of <key>=<value>, for example 'params=key1=v1;key2=v2' (Only when updating a custom rule)");
}
ruleWsSupport.checkQProfileAdminPermission();
try (DbSession dbSession = dbClient.openSession(false)) {
- String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid();
- RuleUpdate update = readRequest(dbSession, request, defaultOrganizationUuid);
- ruleUpdater.update(dbSession, update, userSession);
- UpdateResponse updateResponse = buildResponse(dbSession, update.getRuleKey(), defaultOrganizationUuid);
+ OrganizationDto organization = getOrganization(request, dbSession);
+ RuleUpdate update = readRequest(dbSession, request, organization);
+ ruleUpdater.update(dbSession, update, organization, userSession);
+ UpdateResponse updateResponse = buildResponse(dbSession, update.getRuleKey(), organization);
writeProtobuf(updateResponse, request, response);
}
}
- private RuleUpdate readRequest(DbSession dbSession, Request request, String organizationUuid) {
+ private OrganizationDto getOrganization(Request request, DbSession dbSession) {
+ String organizationKey = ofNullable(request.param(PARAM_ORGANIZATION))
+ .orElseGet(() -> defaultOrganizationProvider.get().getKey());
+ return dbClient.organizationDao().selectByKey(dbSession, organizationKey)
+ .orElseThrow(() -> new IllegalStateException(format("Cannot load organization '%s'", organizationKey)));
+ }
+
+ private RuleUpdate readRequest(DbSession dbSession, Request request, OrganizationDto organization) {
RuleKey key = RuleKey.parse(request.mandatoryParam(PARAM_KEY));
- RuleUpdate update = createRuleUpdate(dbSession, key, organizationUuid);
+ RuleUpdate update = createRuleUpdate(dbSession, key, organization);
readTags(request, update);
readMarkdownNote(request, update);
readDebt(request, update);
return update;
}
- private RuleUpdate createRuleUpdate(DbSession dbSession, RuleKey key, String organizationUuid) {
- Optional<RuleDto> optionalRule = dbClient.ruleDao().selectByKey(dbSession, organizationUuid, key);
- checkFoundWithOptional(optionalRule, "This rule does not exists : " + key);
- RuleDto rule = optionalRule.get();
- if (rule.getTemplateId() != null) {
- return RuleUpdate.createForCustomRule(key);
- } else {
- return RuleUpdate.createForPluginRule(key);
- }
+ private RuleUpdate createRuleUpdate(DbSession dbSession, RuleKey key, OrganizationDto organization) {
+ RuleDto rule = dbClient.ruleDao().selectByKey(dbSession, organization, key)
+ .transform(Optional::of).or(Optional::empty)
+ .orElseThrow(() -> new NotFoundException(format("This rule does not exist: %s", key)));
+ RuleUpdate ruleUpdate = ofNullable(rule.getTemplateId())
+ .map(x -> RuleUpdate.createForCustomRule(key))
+ .orElseGet(() -> RuleUpdate.createForPluginRule(key));
+ ruleUpdate.setOrganization(organization);
+ return ruleUpdate;
}
- private void readTags(Request request, RuleUpdate update) {
+ private static void readTags(Request request, RuleUpdate update) {
String value = request.param(PARAM_TAGS);
if (value != null) {
if (StringUtils.isBlank(value)) {
// else do not touch this field
}
- private void readMarkdownNote(Request request, RuleUpdate update) {
+ private static void readMarkdownNote(Request request, RuleUpdate update) {
String value = request.param(PARAM_MARKDOWN_NOTE);
if (value != null) {
update.setMarkdownNote(value);
// else do not touch this field
}
- private void readDebt(Request request, RuleUpdate update) {
+ private static void readDebt(Request request, RuleUpdate update) {
String value = defaultIfEmpty(request.param(PARAM_REMEDIATION_FN_TYPE), request.param(DEPRECATED_PARAM_REMEDIATION_FN_TYPE));
if (value != null) {
if (StringUtils.isBlank(value)) {
}
}
- private UpdateResponse buildResponse(DbSession dbSession, RuleKey key, String organizationUuid) {
- Optional<RuleDto> optionalRule = dbClient.ruleDao().selectByKey(dbSession, organizationUuid, key);
- checkFoundWithOptional(optionalRule, "Rule not found: " + key);
- RuleDto rule = optionalRule.get();
+ private UpdateResponse buildResponse(DbSession dbSession, RuleKey key, OrganizationDto organization) {
+ RuleDto rule = dbClient.ruleDao().selectByKey(dbSession, organization, key)
+ .transform(Optional::of).or(Optional::empty)
+ .orElseThrow(() -> new NotFoundException(format("Rule not found: %s", key)));
List<RuleDefinitionDto> templateRules = new ArrayList<>(1);
if (rule.getTemplateId() != null) {
- Optional<RuleDefinitionDto> templateRule = dbClient.ruleDao().selectDefinitionById(rule.getTemplateId(), dbSession);
- if (templateRule.isPresent()) {
- templateRules.add(templateRule.get());
- }
+ dbClient.ruleDao().selectDefinitionById(rule.getTemplateId(), dbSession)
+ .transform(Optional::of).or(Optional::empty)
+ .ifPresent(templateRules::add);
}
List<RuleParamDto> ruleParameters = dbClient.ruleDao().selectRuleParamsByRuleIds(dbSession, singletonList(rule.getId()));
UpdateResponse.Builder responseBuilder = UpdateResponse.newBuilder();
.setTemplateRules(templateRules)
.setRuleParameters(ruleParameters)
.setTotal(1L);
- responseBuilder.setRule(mapper.toWsRule(rule, searchResult, Collections.<String>emptySet()));
+ responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.<String>emptySet(), rule.getMetadata()));
return responseBuilder.build();
}
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
private RuleIndex ruleIndex = TESTER.get(RuleIndex.class);
private RuleDao ruleDao = db.ruleDao();
- private String defaultOrganizationUuid;
+ private OrganizationDto defaultOrganization;
@Before
public void before() {
TESTER.clearDbAndIndexes();
dbSession.clearCache();
- defaultOrganizationUuid = TESTER.get(DefaultOrganizationProvider.class).get().getUuid();
+ String defaultOrganizationUuid = TESTER.get(DefaultOrganizationProvider.class).get().getUuid();
+ defaultOrganization = db.organizationDao().selectByUuid(dbSession, defaultOrganizationUuid)
+ .orElseThrow(() -> new IllegalStateException(String.format("Cannot load default organization '%s'", defaultOrganizationUuid)));
}
@After
repository.createRule("x1").setName("x1 name").setHtmlDescription("x1 desc").setTags("tag1");
}
});
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganizationUuid, RuleTesting.XOO_X1);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RuleTesting.XOO_X1);
assertThat(rule.getSystemTags()).containsOnly("tag1");
assertThat(rule.getTags()).isEmpty();
// User adds tag
- TESTER.get(RuleUpdater.class).update(dbSession, RuleUpdate.createForPluginRule(RuleTesting.XOO_X1).setTags(newHashSet("tag2")), userSessionRule);
+ RuleUpdate update = RuleUpdate.createForPluginRule(RuleTesting.XOO_X1)
+ .setTags(newHashSet("tag2"))
+ .setOrganization(defaultOrganization);
+ TESTER.get(RuleUpdater.class).update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.commit();
- rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganizationUuid, RuleTesting.XOO_X1);
+ rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RuleTesting.XOO_X1);
assertThat(rule.getSystemTags()).containsOnly("tag1");
assertThat(rule.getTags()).containsOnly("tag2");
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleParamDto;
private RuleIndexer ruleIndexer;
private ActiveRuleIndexer activeRuleIndexer;
private RuleIndex ruleIndex;
+ private OrganizationDto defaultOrganization;
@Before
public void before() {
ruleIndexer = new RuleIndexer(esTester.client(), dbClient);
ruleIndex = new RuleIndex(esTester.client());
activeRuleIndexer = new ActiveRuleIndexer(system, dbClient, esTester.client());
+ defaultOrganization = dbTester.getDefaultOrganization();
}
@Test
// verify db
assertThat(dbClient.ruleDao().selectAllDefinitions(dbTester.getSession())).hasSize(2);
- RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization().getUuid(), RULE_KEY1);
+ RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization(), RULE_KEY1);
assertThat(rule1.getName()).isEqualTo("One");
assertThat(rule1.getDescription()).isEqualTo("Description of One");
assertThat(rule1.getSeverityString()).isEqualTo(BLOCKER);
assertThat(esTester.getIds(RuleIndexDefinition.INDEX_TYPE_RULE)).containsOnly(RULE_KEY1.toString(), RULE_KEY2.toString());
// user adds tags and sets markdown note
- String organizationUuid = dbTester.getDefaultOrganization().getUuid();
- RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ OrganizationDto defaultOrganization = dbTester.getDefaultOrganization();
+ String organizationUuid = defaultOrganization.getUuid();
+ RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
rule1.setTags(newHashSet("usertag1", "usertag2"));
rule1.setNoteData("user *note*");
rule1.setNoteUserLogin("marius");
execute(new FakeRepositoryV2());
// rule1 has been updated
- rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
assertThat(rule1.getName()).isEqualTo("One v2");
assertThat(rule1.getDescription()).isEqualTo("Description of One v2");
assertThat(rule1.getSeverityString()).isEqualTo(INFO);
assertThat(param.getDefaultValue()).isEqualTo("default1 v2");
// rule2 has been removed -> status set to REMOVED but db row is not deleted
- RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY2);
+ RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2);
assertThat(rule2.getStatus()).isEqualTo(RuleStatus.REMOVED);
assertThat(rule2.getUpdatedAt()).isEqualTo(DATE2.getTime());
// rule3 has been created
- RuleDto rule3 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY3);
+ RuleDto rule3 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY3);
assertThat(rule3).isNotNull();
assertThat(rule3.getStatus()).isEqualTo(RuleStatus.READY);
}
});
- String organizationUuid = dbTester.getDefaultOrganization().getUuid();
- RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ OrganizationDto defaultOrganization = dbTester.getDefaultOrganization();
+ String organizationUuid = defaultOrganization.getUuid();
+ RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
assertThat(rule.getSystemTags()).containsOnly("tag1");
execute(new RulesDefinition() {
}
});
- rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
assertThat(rule.getSystemTags()).containsOnly("tag1", "tag2");
}
});
// rule1 has been updated
- RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization().getUuid(), RuleKey.of("fake", "rule"));
+ RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of("fake", "rule"));
assertThat(rule1.getName()).isEqualTo("Name2");
assertThat(rule1.getDescription()).isEqualTo("Description");
});
// rule1 has been updated
- RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), dbTester.getDefaultOrganization().getUuid(), RuleKey.of("fake", "rule"));
+ RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RuleKey.of("fake", "rule"));
assertThat(rule1.getName()).isEqualTo("Name");
assertThat(rule1.getDescription()).isEqualTo("Desc2");
execute();
String organizationUuid = dbTester.getDefaultOrganization().getUuid();
- RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ RuleDto rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
assertThat(rule.getStatus()).isEqualTo(RuleStatus.REMOVED);
assertThat(ruleIndex.search(new RuleQuery().setKey(RULE_KEY1.toString()), new SearchOptions()).getTotal()).isEqualTo(0);
when(system.now()).thenReturn(DATE3.getTime());
execute(new FakeRepositoryV1());
- rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ rule = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
assertThat(rule.getStatus()).isEqualTo(RuleStatus.BETA);
assertThat(ruleIndex.search(new RuleQuery().setKey(RULE_KEY1.toString()), new SearchOptions()).getTotal()).isEqualTo(1);
}
execute(new FakeRepositoryV1());
String organizationUuid = dbTester.getDefaultOrganization().getUuid();
- RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1);
+ RuleDto rule1 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1);
assertThat(rule1.getCreatedAt()).isEqualTo(DATE1.getTime());
assertThat(rule1.getUpdatedAt()).isEqualTo(DATE1.getTime());
}
assertThat(esTester.getIds(RuleIndexDefinition.INDEX_TYPE_RULE)).containsOnly(RULE_KEY1.toString(), RULE_KEY2.toString());
String organizationUuid = dbTester.getDefaultOrganization().getUuid();
- RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY2);
+ RuleDto rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2);
assertThat(rule2.getStatus()).isEqualTo(RuleStatus.READY);
when(system.now()).thenReturn(DATE2.getTime());
execute(new FakeRepositoryV2());
// On MySQL, need to update a rule otherwise rule2 will be seen as READY, but why ???
- dbClient.ruleDao().update(dbTester.getSession(), dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY1).getDefinition());
+ dbClient.ruleDao().update(dbTester.getSession(), dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY1).getDefinition());
dbTester.getSession().commit();
// rule2 is removed
- rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY2);
+ rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2);
assertThat(rule2.getStatus()).isEqualTo(RuleStatus.REMOVED);
assertThat(ruleIndex.search(new RuleQuery(), new SearchOptions()).getIds()).containsOnly(RULE_KEY1, RULE_KEY3);
dbTester.getSession().commit();
// -> rule2 is still removed, but not update at DATE3
- rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), organizationUuid, RULE_KEY2);
+ rule2 = dbClient.ruleDao().selectOrFailByKey(dbTester.getSession(), defaultOrganization, RULE_KEY2);
assertThat(rule2.getStatus()).isEqualTo(RuleStatus.REMOVED);
assertThat(rule2.getUpdatedAt()).isEqualTo(DATE2.getTime());
dbSession.clearCache();
- RuleDto rule = db.ruleDao().selectOrFailByKey(dbSession, defaultOrganization.getUuid(), customRuleKey);
+ RuleDto rule = db.ruleDao().selectOrFailByKey(dbSession, defaultOrganization, customRuleKey);
assertThat(rule).isNotNull();
assertThat(rule.getKey()).isEqualTo(RuleKey.of("java", "CUSTOM_RULE"));
assertThat(rule.getTemplateId()).isEqualTo(templateRule.getId());
ruleDao.insert(dbSession, RuleTesting.newRule(RULE_KEY).setStatus(RuleStatus.REMOVED));
dbSession.commit();
- RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(Sets.newHashSet("java9"));
+ RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
+ .setTags(Sets.newHashSet("java9"))
+ .setOrganization(defaultOrganization);
try {
- underTest.update(update, userSessionRule);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Rule with REMOVED status cannot be updated: squid:S001");
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY);
assertThat(update.isEmpty()).isTrue();
- underTest.update(update, userSessionRule);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getNoteData()).isEqualTo("my *note*");
assertThat(rule.getNoteUserLogin()).isEqualTo("me");
assertThat(rule.getTags()).containsOnly("tag1");
ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId()));
dbSession.commit();
- RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY);
- update.setMarkdownNote("my *note*");
- underTest.update(update, userSessionRule);
+ RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
+ .setMarkdownNote("my *note*")
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getNoteData()).isEqualTo("my *note*");
assertThat(rule.getNoteUserLogin()).isEqualTo("me");
assertThat(rule.getNoteCreatedAt()).isNotNull();
ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId()));
dbSession.commit();
- RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setMarkdownNote(null);
- underTest.update(update, userSessionRule);
+ RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
+ .setMarkdownNote(null)
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getNoteData()).isNull();
assertThat(rule.getNoteUserLogin()).isNull();
assertThat(rule.getNoteCreatedAt()).isNull();
// java8 is a system tag -> ignore
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(Sets.newHashSet("bug", "java8"));
- underTest.update(update, userSessionRule);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getTags()).containsOnly("bug");
assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc");
ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata());
dbSession.commit();
- RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setTags(null);
- underTest.update(update, userSessionRule);
+ RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
+ .setTags(null)
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getTags()).isEmpty();
assertThat(rule.getSystemTags()).containsOnly("java8", "javadoc");
DefaultDebtRemediationFunction fn = new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "1min");
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
- .setDebtRemediationFunction(fn);
- underTest.update(update, userSessionRule);
+ .setDebtRemediationFunction(fn)
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
// verify debt is overridden
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name());
assertThat(rule.getRemediationGapMultiplier()).isNull();
assertThat(rule.getRemediationBaseEffort()).isEqualTo("1min");
dbSession.commit();
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
- .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "2d", null));
- underTest.update(update, userSessionRule);
+ .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.LINEAR, "2d", null))
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
// verify debt is overridden
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name());
assertThat(rule.getRemediationGapMultiplier()).isEqualTo("2d");
assertThat(rule.getRemediationBaseEffort()).isNull();
dbSession.commit();
RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
- .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "10min"));
- underTest.update(update, userSessionRule);
+ .setDebtRemediationFunction(new DefaultDebtRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE, null, "10min"))
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
// verify debt is overridden
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.CONSTANT_ISSUE.name());
assertThat(rule.getRemediationGapMultiplier()).isNull();
assertThat(rule.getRemediationBaseEffort()).isEqualTo("10min");
ruleDao.insertOrUpdate(dbSession, ruleDto.getMetadata().setRuleId(ruleDto.getId()));
dbSession.commit();
- RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY).setDebtRemediationFunction(null);
- underTest.update(update, userSessionRule);
+ RuleUpdate update = RuleUpdate.createForPluginRule(RULE_KEY)
+ .setDebtRemediationFunction(null)
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
// verify debt is coming from default values
- RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), RULE_KEY);
+ RuleDto rule = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, RULE_KEY);
assertThat(rule.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR.name());
assertThat(rule.getDefRemediationGapMultiplier()).isEqualTo("1d");
assertThat(rule.getDefRemediationBaseEffort()).isEqualTo("5min");
.setMarkdownDescription("New description")
.setSeverity("MAJOR")
.setStatus(RuleStatus.READY)
- .setParameters(ImmutableMap.of("regex", "b.*"));
- underTest.update(update, userSessionRule);
+ .setParameters(ImmutableMap.of("regex", "b.*"))
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
// Verify custom rule is updated
- RuleDto customRuleReloaded = ruleDao.selectOrFailByKey(dbSession, defaultOrganization.getUuid(), customRule.getKey());
+ RuleDto customRuleReloaded = ruleDao.selectOrFailByKey(dbSession, defaultOrganization, customRule.getKey());
assertThat(customRuleReloaded).isNotNull();
assertThat(customRuleReloaded.getName()).isEqualTo("New name");
assertThat(customRuleReloaded.getDescription()).isEqualTo("New description");
.setName("New name")
.setMarkdownDescription("New description")
.setSeverity("MAJOR")
- .setStatus(RuleStatus.READY);
- underTest.update(update, userSessionRule);
+ .setStatus(RuleStatus.READY)
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
// Update custom rule parameter 'regex', add 'message' and remove 'format'
RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey())
- .setParameters(ImmutableMap.of("regex", "b.*", "message", "a message"));
- underTest.update(update, userSessionRule);
+ .setParameters(ImmutableMap.of("regex", "b.*", "message", "a message"))
+ .setOrganization(defaultOrganization);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
dbSession.clearCache();
@Test
public void fail_to_update_custom_rule_when_empty_name() {
// Create template rule
- RuleDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001"));
- ruleDao.insert(dbSession, templateRule.getDefinition());
+ RuleDefinitionDto templateRule = RuleTesting.newTemplateRule(RuleKey.of("java", "S001")).getDefinition();
+ ruleDao.insert(dbSession, templateRule);
// Create custom rule
- RuleDto customRule = RuleTesting.newCustomRule(templateRule);
- ruleDao.insert(dbSession, customRule.getDefinition());
+ RuleDefinitionDto customRule = RuleTesting.newCustomRule(templateRule);
+ ruleDao.insert(dbSession, customRule);
dbSession.commit();
// Update custom rule
RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey())
.setName("")
- .setMarkdownDescription("New desc");
+ .setMarkdownDescription("New desc")
+ .setOrganization(defaultOrganization);
try {
- underTest.update(update, userSessionRule);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The name is missing");
// Update custom rule
RuleUpdate update = RuleUpdate.createForCustomRule(customRule.getKey())
.setName("New name")
- .setMarkdownDescription("");
+ .setMarkdownDescription("")
+ .setOrganization(defaultOrganization);
try {
- underTest.update(update, userSessionRule);
+ underTest.update(dbSession, update, defaultOrganization, userSessionRule);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The description is missing");
import org.sonar.db.DbTester;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.rule.RuleMetadataDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.server.es.EsClient;
import org.sonar.server.es.EsTester;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.rule.RuleUpdater;
-import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleIndexDefinition;
import org.sonar.server.rule.index.RuleIndexer;
import org.sonar.server.tester.UserSessionRule;
import static org.sonar.api.server.debt.DebtRemediationFunction.Type.LINEAR;
import static org.sonar.api.server.debt.DebtRemediationFunction.Type.LINEAR_OFFSET;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES;
+import static org.sonar.db.rule.RuleTesting.setSystemTags;
+import static org.sonar.db.rule.RuleTesting.setTags;
import static org.sonar.server.rule.ws.UpdateAction.DEPRECATED_PARAM_REMEDIATION_FN_COEFF;
import static org.sonar.server.rule.ws.UpdateAction.DEPRECATED_PARAM_REMEDIATION_FN_OFFSET;
import static org.sonar.server.rule.ws.UpdateAction.DEPRECATED_PARAM_REMEDIATION_FN_TYPE;
import static org.sonar.server.rule.ws.UpdateAction.PARAM_KEY;
+import static org.sonar.server.rule.ws.UpdateAction.PARAM_ORGANIZATION;
import static org.sonar.server.rule.ws.UpdateAction.PARAM_REMEDIATION_FN_BASE_EFFORT;
import static org.sonar.server.rule.ws.UpdateAction.PARAM_REMEDIATION_FN_GAP_MULTIPLIER;
import static org.sonar.server.rule.ws.UpdateAction.PARAM_REMEDIATION_FN_TYPE;
+import static org.sonar.server.rule.ws.UpdateAction.PARAM_TAGS;
import static org.sonarqube.ws.MediaTypes.PROTOBUF;
public class UpdateActionTest {
private WsActionTester actionTester = new WsActionTester(underTest);
private OrganizationDto defaultOrganization;
- private RuleIndex ruleIndex = new RuleIndex(esClient);
-
@Before
public void setUp() {
defaultOrganization = dbTester.getDefaultOrganization();
logInAsQProfileAdministrator();
}
+ @Test
+ public void update_tags_for_default_organization() throws IOException {
+ doReturn("interpreted").when(macroInterpreter).interpret(anyString());
+
+ RuleDefinitionDto rule = dbTester.rules().insert(setSystemTags("stag1", "stag2"));
+ dbTester.rules().insertOrUpdateMetadata(rule, defaultOrganization, setTags("tag1", "tag2"));
+
+ TestRequest request = actionTester.newRequest().setMethod("POST")
+ .setMediaType(PROTOBUF)
+ .setParam(PARAM_KEY, rule.getKey().toString())
+ .setParam(PARAM_TAGS, "tag2,tag3");
+ TestResponse response = request.execute();
+ Rules.UpdateResponse result = Rules.UpdateResponse.parseFrom(response.getInputStream());
+
+ Rules.Rule updatedRule = result.getRule();
+ assertThat(updatedRule).isNotNull();
+
+ assertThat(updatedRule.getKey()).isEqualTo(rule.getKey().toString());
+ assertThat(updatedRule.getSysTags().getSysTagsList()).containsExactly(rule.getSystemTags().toArray(new String[0]));
+ assertThat(updatedRule.getTags().getTagsList()).containsExactly("tag2", "tag3");
+ }
+
+ @Test
+ public void update_tags_for_specific_organization() throws IOException {
+ doReturn("interpreted").when(macroInterpreter).interpret(anyString());
+
+ OrganizationDto organization = dbTester.organizations().insert();
+
+ RuleDefinitionDto rule = dbTester.rules().insert(setSystemTags("stag1", "stag2"));
+ dbTester.rules().insertOrUpdateMetadata(rule, organization, setTags("tagAlt1", "tagAlt2"));
+
+ TestRequest request = actionTester.newRequest().setMethod("POST")
+ .setMediaType(PROTOBUF)
+ .setParam(PARAM_KEY, rule.getKey().toString())
+ .setParam(PARAM_TAGS, "tag2,tag3")
+ .setParam(PARAM_ORGANIZATION, organization.getKey());
+ TestResponse response = request.execute();
+ Rules.UpdateResponse result = Rules.UpdateResponse.parseFrom(response.getInputStream());
+
+ Rules.Rule updatedRule = result.getRule();
+ assertThat(updatedRule).isNotNull();
+
+ // check response
+ assertThat(updatedRule.getKey()).isEqualTo(rule.getKey().toString());
+ assertThat(updatedRule.getSysTags().getSysTagsList()).containsExactly(rule.getSystemTags().toArray(new String[0]));
+ assertThat(updatedRule.getTags().getTagsList()).containsExactly("tag2", "tag3");
+
+ // check database
+ RuleMetadataDto metadataOfSpecificOrg = dbTester.getDbClient().ruleDao().selectMetadataByKey(dbTester.getSession(), rule.getKey(), organization)
+ .orElseThrow(() -> new IllegalStateException("Cannot load metadata"));
+ assertThat(metadataOfSpecificOrg.getTags()).containsExactly("tag2", "tag3");
+ }
+
@Test
public void update_rule_remediation_function() throws IOException {
doReturn("interpreted").when(macroInterpreter).interpret(anyString());
+ OrganizationDto organization = dbTester.organizations().insert();
+
RuleDefinitionDto rule = dbTester.rules().insert(
r -> r.setDefRemediationFunction(LINEAR.toString()),
r -> r.setDefRemediationGapMultiplier("10d"),
TestRequest request = actionTester.newRequest().setMethod("POST")
.setMediaType(PROTOBUF)
.setParam("key", rule.getKey().toString())
+ .setParam(PARAM_ORGANIZATION, organization.getKey())
.setParam(PARAM_REMEDIATION_FN_TYPE, newOffset)
.setParam(PARAM_REMEDIATION_FN_GAP_MULTIPLIER, newMultiplier)
.setParam(PARAM_REMEDIATION_FN_BASE_EFFORT, newEffort);
assertThat(updatedRule.getRemFnType()).isEqualTo(newOffset);
assertThat(updatedRule.getRemFnGapMultiplier()).isEqualTo(newMultiplier);
assertThat(updatedRule.getRemFnBaseEffort()).isEqualTo(newEffort);
+
+ // check database
+ RuleMetadataDto metadataOfSpecificOrg = dbTester.getDbClient().ruleDao().selectMetadataByKey(dbTester.getSession(), rule.getKey(), organization)
+ .orElseThrow(() -> new IllegalStateException("Cannot load metadata"));
+ assertThat(metadataOfSpecificOrg.getRemediationFunction()).isEqualTo(newOffset);
+ assertThat(metadataOfSpecificOrg.getRemediationGapMultiplier()).isEqualTo(newMultiplier);
+ assertThat(metadataOfSpecificOrg.getRemediationBaseEffort()).isEqualTo(newEffort);
}
@Test
"internalKey": "InternalKeyS001",
"isTemplate": false,
"templateKey": "java:S001",
- "tags": ["tag1", "tag2"],
"sysTags": ["systag1", "systag2"],
- "debtRemFnType": "LINEAR_OFFSET",
- "debtRemFnCoeff": "5d",
- "debtRemFnOffset": "10h",
"lang": "js",
"params": [
{