|
|
@@ -0,0 +1,84 @@
|
|
|
+package cn.seecoder.data.server.service.Impl;
|
|
|
+
|
|
|
+import cn.seecoder.data.server.domain.sonar.SonarCoderDao;
|
|
|
+import cn.seecoder.data.server.dto.sonarqube.ComponentTreeDto;
|
|
|
+import cn.seecoder.data.server.repository.SonarCoderRepository;
|
|
|
+import cn.seecoder.data.server.service.SonarqubeService;
|
|
|
+import cn.seecoder.data.server.utils.enums.ErrorCodeEnum;
|
|
|
+import cn.seecoder.data.server.utils.exception.GlobalException;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.core.ParameterizedTypeReference;
|
|
|
+import org.springframework.http.HttpMethod;
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
+
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.LinkedList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class SonarqubeServiceImpl implements SonarqubeService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SonarCoderRepository sonarCoderRepository;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+
|
|
|
+ @Value("${sys.sonarqube.url}")
|
|
|
+ private String sonarBaseUrl;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public double getSonarScoreOfUser(int userId) { // 所有项目取平均分 , 100.0 满分
|
|
|
+ List<ComponentTreeDto> componentTreeDtos = getSonarDataOfUser(userId);
|
|
|
+ double sum = componentTreeDtos.stream().mapToDouble(componentTreeDto -> handleMeasures(componentTreeDto.getBaseComponent().getMeasures())).sum();
|
|
|
+ return sum / componentTreeDtos.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ private double handleMeasures(List<ComponentTreeDto.Measure> measures) { // 单个项目得分计算
|
|
|
+ AtomicReference<Double> sum = new AtomicReference<>(0.0);
|
|
|
+ measures.forEach(measure -> {
|
|
|
+ if(measure.getMetric().equals("duplicated_lines_density")) sum.updateAndGet(v -> (double) (v + 100.0 - Double.parseDouble(measure.getValue())));
|
|
|
+ else sum.updateAndGet(v -> (double) (v + (5 - (measure.getValue().charAt(0) - 'A')) * 20.0));
|
|
|
+ });
|
|
|
+ return sum.get() / measures.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<ComponentTreeDto> getSonarDataOfUser(int userId) { // note: 以后devcloud接入sonar之后,此处源码需要修改
|
|
|
+ // 1. fetch sonarName by userId
|
|
|
+ List<SonarCoderDao> sonarCoderDaos = sonarCoderRepository.findAllByUserId(userId);
|
|
|
+ // 2. fetch sonarComponentTreeDto by sonarName
|
|
|
+ List<ComponentTreeDto> componentTreeDtos = new LinkedList<>();
|
|
|
+ sonarCoderDaos.forEach(sonarCoderDao -> {
|
|
|
+ try {
|
|
|
+ ComponentTreeDto componentTreeDto = fetchSonarDataBySonarName(sonarCoderDao.getSonarName());
|
|
|
+ componentTreeDtos.add(componentTreeDto);
|
|
|
+ } catch (Exception e){
|
|
|
+ LoggerFactory.getLogger(getClass()).error("sonar: Cannot get data by sonarname '" + sonarCoderDao.getSonarName() + "' !" );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return componentTreeDtos;
|
|
|
+ }
|
|
|
+
|
|
|
+ private ComponentTreeDto fetchSonarDataBySonarName(String sonarName) {
|
|
|
+ String sonarUrl = sonarBaseUrl + "/api/measures/component_tree?" +
|
|
|
+ "qualifiers=TRK" +
|
|
|
+ "&p=1&ps=500" +
|
|
|
+ "&metricKeys=reliability_rating,security_rating,sqale_rating,duplicated_lines_density" +
|
|
|
+ "&component=" +
|
|
|
+ sonarName;
|
|
|
+ ParameterizedTypeReference<ComponentTreeDto> responseType = new ParameterizedTypeReference<ComponentTreeDto>() {};
|
|
|
+ try {
|
|
|
+ ResponseEntity<ComponentTreeDto> r = restTemplate.exchange(sonarUrl,HttpMethod.GET,null,responseType,new HashMap<>());
|
|
|
+ ComponentTreeDto body = r.getBody();
|
|
|
+ return body;
|
|
|
+ }catch (Throwable e) {
|
|
|
+ throw new GlobalException(ErrorCodeEnum.SERVICE_ERROR_C0007);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|