Package org.sonar.server.issue.ws

Source Code of org.sonar.server.issue.ws.IssueShowAction

/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube 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.
*
* SonarQube 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.issue.ws;

import com.google.common.io.Resources;
import org.sonar.api.i18n.I18n;
import org.sonar.api.issue.ActionPlan;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.IssueComment;
import org.sonar.api.issue.internal.DefaultIssueComment;
import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.api.server.debt.DebtCharacteristic;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
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.server.ws.WebService;
import org.sonar.api.user.User;
import org.sonar.api.user.UserFinder;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.markdown.Markdown;
import org.sonar.server.db.DbClient;
import org.sonar.server.debt.DebtModelService;
import org.sonar.server.issue.IssueChangelog;
import org.sonar.server.issue.IssueChangelogService;
import org.sonar.server.issue.IssueCommentService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleService;
import org.sonar.server.user.UserSession;

import javax.annotation.CheckForNull;
import javax.annotation.Nullable;

import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.google.common.collect.Maps.newHashMap;

public class IssueShowAction implements RequestHandler {

  public static final String SHOW_ACTION = "show";

  private final DbClient dbClient;

  private final IssueService issueService;
  private final IssueChangelogService issueChangelogService;
  private final IssueCommentService commentService;
  private final IssueActionsWriter actionsWriter;
  private final ActionPlanService actionPlanService;
  private final UserFinder userFinder;
  private final DebtModelService debtModel;
  private final RuleService ruleService;
  private final I18n i18n;
  private final Durations durations;

  public IssueShowAction(DbClient dbClient, IssueService issueService, IssueChangelogService issueChangelogService, IssueCommentService commentService,
                         IssueActionsWriter actionsWriter, ActionPlanService actionPlanService, UserFinder userFinder, DebtModelService debtModel, RuleService ruleService,
                         I18n i18n, Durations durations) {
    this.dbClient = dbClient;
    this.issueService = issueService;
    this.issueChangelogService = issueChangelogService;
    this.commentService = commentService;
    this.actionsWriter = actionsWriter;
    this.actionPlanService = actionPlanService;
    this.userFinder = userFinder;
    this.debtModel = debtModel;
    this.ruleService = ruleService;
    this.i18n = i18n;
    this.durations = durations;
  }

  void define(WebService.NewController controller) {
    WebService.NewAction action = controller.createAction(SHOW_ACTION)
      .setDescription("Detail of issue")
      .setSince("4.2")
      .setInternal(true)
      .setHandler(this)
      .setResponseExample(Resources.getResource(this.getClass(), "example-show.json"));
    action.createParam("key")
      .setDescription("Issue key")
      .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
  }

  @Override
  public void handle(Request request, Response response) {
    String issueKey = request.mandatoryParam("key");

    JsonWriter json = response.newJsonWriter();
    json.beginObject().name("issue").beginObject();

    DbSession session = dbClient.openSession(false);
    try {
      Issue issue = issueService.getByKey(issueKey);

      writeIssue(session, issue, json);
      actionsWriter.writeActions(issue, json);
      actionsWriter.writeTransitions(issue, json);
      writeComments(issue, json);
      writeChangelog(issue, json);

    } finally {
      session.close();
    }

    json.endObject().endObject().close();
  }

  private void writeIssue(DbSession session, Issue issue, JsonWriter json) {
    String actionPlanKey = issue.actionPlanKey();
    ActionPlan actionPlan = actionPlanKey != null ? actionPlanService.findByKey(actionPlanKey, UserSession.get()) : null;
    Duration debt = issue.debt();
    Rule rule = ruleService.getNonNullByKey(issue.ruleKey());
    Date updateDate = issue.updateDate();
    Date closeDate = issue.closeDate();

    json
      .prop("key", issue.key())
      .prop("rule", issue.ruleKey().toString())
      .prop("ruleName", rule.name())
      .prop("line", issue.line())
      .prop("message", issue.message())
      .prop("resolution", issue.resolution())
      .prop("status", issue.status())
      .prop("severity", issue.severity())
      .prop("author", issue.authorLogin())
      .prop("actionPlan", actionPlanKey)
      .prop("actionPlanName", actionPlan != null ? actionPlan.name() : null)
      .prop("debt", debt != null ? durations.encode(debt) : null)
      .prop("creationDate", DateUtils.formatDateTime(issue.creationDate()))
      .prop("fCreationDate", formatDate(issue.creationDate()))
      .prop("updateDate", updateDate != null ? DateUtils.formatDateTime(updateDate) : null)
      .prop("fUpdateDate", formatDate(updateDate))
      .prop("fUpdateAge", formatAgeDate(updateDate))
      .prop("closeDate", closeDate != null ? DateUtils.formatDateTime(closeDate) : null)
      .prop("fCloseDate", formatDate(issue.closeDate()));

    addComponents(session, issue, json);
    addUserWithLabel(issue.assignee(), "assignee", json);
    addUserWithLabel(issue.reporter(), "reporter", json);
    addCharacteristics(rule, json);
  }

  private void addComponents(DbSession session, Issue issue, JsonWriter json) {
    ComponentDto component = dbClient.componentDao().getByUuid(session, issue.componentUuid());
    Long subProjectId = component.subProjectId();
    ComponentDto subProject = subProjectId != null ? dbClient.componentDao().getNullableById(subProjectId, session) : null;
    ComponentDto project = dbClient.componentDao().getByUuid(session, component.projectUuid());

    String projectName = project.longName() != null ? project.longName() : project.name();
    // Do not display sub project long name if sub project and project are the same
    boolean displaySubProjectLongName = subProject != null && !subProject.getId().equals(project.getId());
    String subProjectName = displaySubProjectLongName ? subProject.longName() != null ? subProject.longName() : subProject.name() : null;

    json
      .prop("component", component.key())
      .prop("componentLongName", component.longName())
      .prop("componentQualifier", component.qualifier())
      .prop("componentEnabled", component.isEnabled())
      .prop("project", project.key())
      .prop("projectName", projectName)
      .prop("subProjectName", subProjectName);
  }

  private void writeComments(Issue issue, JsonWriter json) {
    json.name("comments").beginArray();
    String login = UserSession.get().login();

    Map<String, User> usersByLogin = newHashMap();
    List<DefaultIssueComment> comments = commentService.findComments(issue.key());
    for (IssueComment comment : comments) {
      String userLogin = comment.userLogin();
      User user = usersByLogin.get(userLogin);
      if (user == null) {
        user = userFinder.findByLogin(userLogin);
        if (user != null) {
          usersByLogin.put(userLogin, user);
        }
      }
    }

    for (IssueComment comment : comments) {
      String userLogin = comment.userLogin();
      User user = usersByLogin.get(userLogin);
      json
        .beginObject()
        .prop("key", comment.key())
        .prop("userName", user != null ? user.name() : null)
        .prop("raw", comment.markdownText())
        .prop("html", Markdown.convertToHtml(comment.markdownText()))
        .prop("createdAt", DateUtils.formatDateTime(comment.createdAt()))
        .prop("fCreatedAge", formatAgeDate(comment.createdAt()))
        .prop("updatable", login != null && login.equals(userLogin))
        .endObject();
    }
    json.endArray();
  }

  private void writeChangelog(Issue issue, JsonWriter json) {
    json.name("changelog").beginArray()
      .beginObject()
      .prop("creationDate", DateUtils.formatDateTime(issue.creationDate()))
      .prop("fCreationDate", formatDate(issue.creationDate()))
      .name("diffs").beginArray()
      .value(i18n.message(UserSession.get().locale(), "created", null))
      .endArray()
      .endObject();

    IssueChangelog changelog = issueChangelogService.changelog(issue);
    for (FieldDiffs diffs : changelog.changes()) {
      User user = changelog.user(diffs);
      json
        .beginObject()
        .prop("userName", user != null ? user.name() : null)
        .prop("creationDate", DateUtils.formatDateTime(diffs.creationDate()))
        .prop("fCreationDate", formatDate(diffs.creationDate()));
      json.name("diffs").beginArray();
      List<String> diffsFormatted = issueChangelogService.formatDiffs(diffs);
      for (String diff : diffsFormatted) {
        json.value(diff);
      }
      json.endArray();
      json.endObject();
    }
    json.endArray();
  }

  private void addUserWithLabel(@Nullable String value, String field, JsonWriter json) {
    if (value != null) {
      User user = userFinder.findByLogin(value);
      json
        .prop(field, value)
        .prop(field + "Name", user != null ? user.name() : null);
    }
  }

  @CheckForNull
  private String formatDate(@Nullable Date date) {
    if (date != null) {
      return i18n.formatDateTime(UserSession.get().locale(), date);
    }
    return null;
  }

  @CheckForNull
  private String formatAgeDate(@Nullable Date date) {
    if (date != null) {
      return i18n.ageFromNow(UserSession.get().locale(), date);
    }
    return null;
  }

  private void addCharacteristics(Rule rule, JsonWriter json) {
    String subCharacteristicKey = rule.debtCharacteristicKey();
    DebtCharacteristic subCharacteristic = characteristicByKey(subCharacteristicKey);
    if (subCharacteristic != null) {
      json.prop("subCharacteristic", subCharacteristic.name());
      DebtCharacteristic characteristic = characteristicById(((DefaultDebtCharacteristic) subCharacteristic).parentId());
      json.prop("characteristic", characteristic != null ? characteristic.name() : null);
    }
  }

  @CheckForNull
  private DebtCharacteristic characteristicById(@Nullable Integer id) {
    if (id != null) {
      return debtModel.characteristicById(id);
    }
    return null;
  }

  @CheckForNull
  private DebtCharacteristic characteristicByKey(@Nullable String key) {
    if (key != null) {
      return debtModel.characteristicByKey(key);
    }
    return null;
  }
}
TOP

Related Classes of org.sonar.server.issue.ws.IssueShowAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.