import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
+import org.sonar.api.technicaldebt.server.Characteristic;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager;
import org.sonar.markdown.Markdown;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.issue.ActionService;
private final IssueChangelogService issueChangelogService;
private final ActionService actionService;
private final TechnicalDebtFormatter technicalDebtFormatter;
+ private final DefaultTechnicalDebtManager technicalDebtManager;
private final I18n i18n;
public IssueShowWsHandler(IssueFinder issueFinder, IssueService issueService, IssueChangelogService issueChangelogService, ActionService actionService,
- TechnicalDebtFormatter technicalDebtFormatter, I18n i18n) {
+ TechnicalDebtFormatter technicalDebtFormatter, DefaultTechnicalDebtManager technicalDebtManager, I18n i18n) {
this.issueFinder = issueFinder;
this.issueService = issueService;
this.issueChangelogService = issueChangelogService;
this.actionService = actionService;
this.technicalDebtFormatter = technicalDebtFormatter;
+ this.technicalDebtManager = technicalDebtManager;
this.i18n = i18n;
}
addUserWithLabel(result, issue.assignee(), "assignee", json);
addUserWithLabel(result, issue.reporter(), "reporter", json);
+ addCharacteristics(result, issue, json);
+ }
+
+ private void addCharacteristics(IssueQueryResult result, DefaultIssue issue, JsonWriter json) {
+ Characteristic requirement = technicalDebtManager.findRequirementByRule(result.rule(issue));
+ // Requirement can be null if it has been disabled
+ if (requirement != null) {
+ Characteristic characteristic = technicalDebtManager.findCharacteristicById(requirement.rootId());
+ json.prop("characteristic", characteristic != null ? characteristic.name() : null);
+ Characteristic subCharacteristic = technicalDebtManager.findCharacteristicById(requirement.parentId());
+ json.prop("subCharacteristic", subCharacteristic != null ? subCharacteristic.name() : null);
+ }
}
private void writeTransitions(Issue issue, JsonWriter json) {
unassigned: '<%= escape_javascript message('unassigned') -%>',
assignedToMe: '<%= escape_javascript message('assigned_to_me') -%>',
filtersList: '<%= escape_javascript message('issue_filter.filter_list') -%>',
- commentConfirmDelete: '<%= escape_javascript message('issue.comment.delete_confirm_message') -%>',
+ commentConfirmDelete: '<%= escape_javascript message('issue.comment.delete_confirm_message') -%>',
+ requirementRemoved: '<%= escape_javascript message('issue.technical_debt_deleted') -%>',
select2: {
noMatches: '<%= escape_javascript message('select2.noMatches') -%>',
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
import org.sonar.api.server.ws.WsTester;
+import org.sonar.api.technicaldebt.server.Characteristic;
+import org.sonar.api.technicaldebt.server.internal.DefaultCharacteristic;
import org.sonar.api.user.User;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultActionPlan;
import org.sonar.core.issue.DefaultIssueQueryResult;
import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.technicaldebt.DefaultTechnicalDebtManager;
import org.sonar.core.user.DefaultUser;
import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueChangelog;
@Mock
TechnicalDebtFormatter technicalDebtFormatter;
+ @Mock
+ DefaultTechnicalDebtManager technicalDebtManager;
+
@Mock
I18n i18n;
when(i18n.message(any(Locale.class), eq("created"), eq((String) null))).thenReturn("Created");
- tester = new WsTester(new IssuesWs(new IssueShowWsHandler(issueFinder, issueService, issueChangelogService, actionService, technicalDebtFormatter, i18n)));
+ tester = new WsTester(new IssuesWs(new IssueShowWsHandler(issueFinder, issueService, issueChangelogService, actionService, technicalDebtFormatter, technicalDebtManager, i18n)));
}
@Test
request.execute().assertJson(getClass(), "show_issue_with_technical_debt.json");
}
+ @Test
+ public void show_issue_with_characteristics() throws Exception {
+ WorkDayDuration technicalDebt = WorkDayDuration.of(1, 2, 0);
+ Issue issue = createStandardIssue()
+ .setTechnicalDebt(technicalDebt);
+ issues.add(issue);
+
+ Characteristic requirement = new DefaultCharacteristic().setId(5).setParentId(2).setRootId(1);
+ Characteristic characteristic = new DefaultCharacteristic().setId(1).setName("Maintainability");
+ Characteristic subCharacteristic = new DefaultCharacteristic().setId(2).setName("Readability");
+ when(technicalDebtManager.findRequirementByRule(result.rule(issue))).thenReturn(requirement);
+ when(technicalDebtManager.findCharacteristicById(1)).thenReturn(characteristic);
+ when(technicalDebtManager.findCharacteristicById(2)).thenReturn(subCharacteristic);
+
+ MockUserSession.set();
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_characteristics.json");
+ }
+
@Test
public void show_issue_with_dates() throws Exception {
Date creationDate = DateUtils.parseDateTime("2014-01-22T19:10:03+0100");
}
private DefaultIssue createStandardIssue() {
- DefaultIssue issue = createIssue();
+ DefaultIssue issue = createIssue();
addComponentAndProject();
return issue;
}
.setCreationDate(issue_creation_date);
}
- private void addComponentAndProject(){
+ private void addComponentAndProject() {
Component component = mock(Component.class);
when(component.key()).thenReturn("org.sonar.server.issue.IssueClient");
when(component.longName()).thenReturn("SonarQube :: Issue Client");
--- /dev/null
+{
+ "issue": {
+ "key": "ABCD",
+ "component": "org.sonar.server.issue.IssueClient",
+ "componentLongName": "SonarQube :: Issue Client",
+ "componentQualifier": "FIL",
+ "project": "org.sonar.Sonar",
+ "projectLongName": "SonarQube",
+ "rule": "squid:AvoidCycle",
+ "ruleName": "Avoid cycle",
+ "characteristic": "Maintainability",
+ "subCharacteristic": "Readability",
+ "creationDate": "2014-01-22T19:10:03+0100",
+ "fCreationDate": "Jan 22, 2014 10:03 AM",
+ "transitions": [],
+ "actions": [],
+ "comments": [],
+ "changelog": [
+ {
+ "creationDate": "2014-01-22T19:10:03+0100",
+ "fCreationDate": "Jan 22, 2014 10:03 AM",
+ "diffs": ["Created"]
+ }
+ ]
+ }
+}