All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.server.rule.ws.ActiveRuleCompleter Maven / Gradle / Ivy

There is a newer version: 7.2.1
Show newest version
/*
 * 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.rule.ws;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.util.stream.MoreCollectors;
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;
import org.sonar.db.qualityprofile.OrgActiveRuleDto;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.qualityprofile.ActiveRule;
import org.sonar.server.rule.index.RuleQuery;
import org.sonarqube.ws.Rules;
import org.sonarqube.ws.Rules.SearchResponse;

import static com.google.common.base.Strings.nullToEmpty;
import static java.util.Collections.singletonList;
import static org.sonar.core.util.Protobuf.setNullable;
import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;

/**
 * Add details about active rules to api/rules/search and api/rules/show
 * web services.
 */
@ServerSide
public class ActiveRuleCompleter {

  private final DbClient dbClient;
  private final Languages languages;

  public ActiveRuleCompleter(DbClient dbClient, Languages languages) {
    this.dbClient = dbClient;
    this.languages = languages;
  }

  void completeSearch(DbSession dbSession, RuleQuery query, List rules, SearchResponse.Builder searchResponse) {
    Set profileUuids = writeActiveRules(dbSession, searchResponse, query, rules);
    searchResponse.setQProfiles(buildQProfiles(dbSession, profileUuids));
  }

  private Set writeActiveRules(DbSession dbSession, SearchResponse.Builder response, RuleQuery query, List rules) {
    final Set profileUuids = new HashSet<>();
    Rules.Actives.Builder activesBuilder = response.getActivesBuilder();

    QProfileDto profile = query.getQProfile();
    if (profile != null) {
      // Load details of active rules on the selected profile
      List activeRules = dbClient.activeRuleDao().selectByProfile(dbSession, profile);
      Map activeRuleByRuleKey = activeRules.stream()
        .collect(uniqueIndex(ActiveRuleDto::getRuleKey));
      ListMultimap activeRuleParamsByActiveRuleKey = loadParams(dbSession, activeRules);

      for (RuleDto rule : rules) {
        OrgActiveRuleDto activeRule = activeRuleByRuleKey.get(rule.getKey());
        if (activeRule != null) {
          profileUuids.addAll(writeActiveRules(rule.getKey(), singletonList(activeRule), activeRuleParamsByActiveRuleKey, activesBuilder));
        }
      }
    } else {
      // Load details of all active rules
      List ruleIds = Lists.transform(rules, RuleDto::getId);
      List activeRules = dbClient.activeRuleDao().selectByRuleIds(dbSession, query.getOrganization(), ruleIds);
      Multimap activeRulesByRuleKey = activeRules.stream()
        .collect(MoreCollectors.index(OrgActiveRuleDto::getRuleKey));
      ListMultimap activeRuleParamsByActiveRuleKey = loadParams(dbSession, activeRules);
      rules.forEach(rule -> profileUuids.addAll(writeActiveRules(rule.getKey(), activeRulesByRuleKey.get(rule.getKey()), activeRuleParamsByActiveRuleKey, activesBuilder)));
    }

    response.setActives(activesBuilder);
    return profileUuids;
  }

  private static Set writeActiveRules(RuleKey ruleKey, Collection activeRules,
    ListMultimap activeRuleParamsByActiveRuleKey, Rules.Actives.Builder activesBuilder) {
    final Set profileUuids = new HashSet<>();
    Rules.ActiveList.Builder activeRulesListResponse = Rules.ActiveList.newBuilder();
    for (OrgActiveRuleDto activeRule : activeRules) {
      activeRulesListResponse.addActiveList(buildActiveRuleResponse(activeRule, activeRuleParamsByActiveRuleKey.get(activeRule.getKey())));
      profileUuids.add(activeRule.getProfileUuid());
    }
    activesBuilder
      .getMutableActives()
      .put(ruleKey.toString(), activeRulesListResponse.build());
    return profileUuids;
  }

  private ListMultimap loadParams(DbSession dbSession, List activeRules) {
    Map activeRuleIdsByKey = new HashMap<>();
    for (OrgActiveRuleDto activeRule : activeRules) {
      activeRuleIdsByKey.put(activeRule.getId(), activeRule.getKey());
    }
    List activeRuleParams = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, Lists.transform(activeRules, ActiveRuleDto::getId));
    ListMultimap activeRuleParamsByActiveRuleKey = ArrayListMultimap.create(activeRules.size(), 10);
    for (ActiveRuleParamDto activeRuleParam : activeRuleParams) {
      ActiveRuleKey activeRuleKey = activeRuleIdsByKey.get(activeRuleParam.getActiveRuleId());
      activeRuleParamsByActiveRuleKey.put(activeRuleKey, activeRuleParam);
    }

    return activeRuleParamsByActiveRuleKey;
  }

  List completeShow(DbSession dbSession, OrganizationDto organization, RuleDefinitionDto rule) {
    List activeRules = dbClient.activeRuleDao().selectByRuleId(dbSession, organization, rule.getId());
    Map activeRuleIdsByKey = new HashMap<>();
    for (OrgActiveRuleDto activeRuleDto : activeRules) {
      activeRuleIdsByKey.put(activeRuleDto.getId(), activeRuleDto.getKey());
    }

    List activeRuleIds = activeRules.stream().map(ActiveRuleDto::getId).collect(Collectors.toList());
    List activeRuleParams = dbClient.activeRuleDao().selectParamsByActiveRuleIds(dbSession, activeRuleIds);
    ListMultimap activeRuleParamsByActiveRuleKey = ArrayListMultimap.create(activeRules.size(), 10);
    for (ActiveRuleParamDto activeRuleParamDto : activeRuleParams) {
      ActiveRuleKey activeRuleKey = activeRuleIdsByKey.get(activeRuleParamDto.getActiveRuleId());
      activeRuleParamsByActiveRuleKey.put(activeRuleKey, activeRuleParamDto);
    }

    return activeRules.stream()
      .map(activeRule -> buildActiveRuleResponse(activeRule, activeRuleParamsByActiveRuleKey.get(activeRule.getKey())))
      .collect(Collectors.toList());
  }

  private static Rules.Active buildActiveRuleResponse(OrgActiveRuleDto activeRule, List parameters) {
    Rules.Active.Builder builder = Rules.Active.newBuilder();
    builder.setQProfile(activeRule.getProfileUuid());
    String inheritance = activeRule.getInheritance();
    builder.setInherit(inheritance != null ? inheritance : ActiveRule.Inheritance.NONE.name());
    builder.setSeverity(activeRule.getSeverityString());
    builder.setCreatedAt(DateUtils.formatDateTime(activeRule.getCreatedAt()));
    Rules.Active.Param.Builder paramBuilder = Rules.Active.Param.newBuilder();
    for (ActiveRuleParamDto parameter : parameters) {
      builder.addParams(paramBuilder.clear()
        .setKey(parameter.getKey())
        .setValue(nullToEmpty(parameter.getValue())));
    }

    return builder.build();
  }

  private Rules.QProfiles.Builder buildQProfiles(DbSession dbSession, Set profileUuids) {
    Rules.QProfiles.Builder result = Rules.QProfiles.newBuilder();
    if (profileUuids.isEmpty()) {
      return result;
    }

    // load profiles
    Map profilesByUuid = dbClient.qualityProfileDao().selectByUuids(dbSession, new ArrayList<>(profileUuids))
      .stream()
      .collect(Collectors.toMap(QProfileDto::getKee, Function.identity()));

    // load associated parents
    List parentUuids = profilesByUuid.values().stream()
      .map(QProfileDto::getParentKee)
      .filter(StringUtils::isNotEmpty)
      .filter(uuid -> !profilesByUuid.containsKey(uuid))
      .collect(MoreCollectors.toList());
    if (!parentUuids.isEmpty()) {
      dbClient.qualityProfileDao().selectByUuids(dbSession, parentUuids)
        .forEach(p -> profilesByUuid.put(p.getKee(), p));
    }

    Map qProfilesMapResponse = result.getMutableQProfiles();
    profilesByUuid.values().forEach(p -> writeProfile(qProfilesMapResponse, p));

    return result;
  }

  private void writeProfile(Map profilesResponse, QProfileDto profile) {
    Rules.QProfile.Builder profileResponse = Rules.QProfile.newBuilder();
    setNullable(profile.getName(), profileResponse::setName);

    if (profile.getLanguage() != null) {
      profileResponse.setLang(profile.getLanguage());
      Language language = languages.get(profile.getLanguage());
      String langName = language == null ? profile.getLanguage() : language.getName();
      profileResponse.setLangName(langName);
    }
    setNullable(profile.getParentKee(), profileResponse::setParent);

    profilesResponse.put(profile.getKee(), profileResponse.build());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy