3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectanalysis.step;
22 import java.util.Objects;
23 import java.util.function.Function;
24 import java.util.stream.StreamSupport;
25 import org.sonar.api.utils.System2;
26 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
27 import org.sonar.ce.task.projectanalysis.component.Component;
28 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
29 import org.sonar.ce.task.projectanalysis.event.Event;
30 import org.sonar.ce.task.projectanalysis.event.EventRepository;
31 import org.sonar.ce.task.step.ComputationStep;
32 import org.sonar.core.util.UuidFactory;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbSession;
35 import org.sonar.db.event.EventDto;
37 public class PersistEventsStep implements ComputationStep {
39 private final DbClient dbClient;
40 private final System2 system2;
41 private final AnalysisMetadataHolder analysisMetadataHolder;
42 private final TreeRootHolder treeRootHolder;
43 private final EventRepository eventRepository;
44 private final UuidFactory uuidFactory;
46 public PersistEventsStep(DbClient dbClient, System2 system2, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
47 EventRepository eventRepository, UuidFactory uuidFactory) {
48 this.dbClient = dbClient;
49 this.system2 = system2;
50 this.treeRootHolder = treeRootHolder;
51 this.analysisMetadataHolder = analysisMetadataHolder;
52 this.eventRepository = eventRepository;
53 this.uuidFactory = uuidFactory;
57 public void execute(ComputationStep.Context context) {
58 try (DbSession dbSession = dbClient.openSession(false)) {
59 long analysisDate = analysisMetadataHolder.getAnalysisDate();
60 new PersistEvent(dbSession, analysisDate).process(treeRootHolder.getRoot());
66 public String getDescription() {
67 return "Persist events";
70 private class PersistEvent {
71 private final DbSession session;
72 private final long analysisDate;
74 PersistEvent(DbSession session, long analysisDate) {
75 this.session = session;
76 this.analysisDate = analysisDate;
79 public void process(Component project) {
80 processEvents(session, project, analysisDate);
81 saveVersionEvent(session, project, analysisDate);
84 private void processEvents(DbSession session, Component component, Long analysisDate) {
85 Function<Event, EventDto> eventToEventDto = event -> newBaseEvent(component, analysisDate)
86 .setName(event.getName())
87 .setCategory(convertCategory(event.getCategory()))
88 .setDescription(event.getDescription())
89 .setData(event.getData());
91 for (EventDto batchEventDto : StreamSupport.stream(eventRepository.getEvents().spliterator(), false).map(eventToEventDto).toList()) {
92 dbClient.eventDao().insert(session, batchEventDto);
96 private void saveVersionEvent(DbSession session, Component component, Long analysisDate) {
97 String projectVersion = component.getProjectAttributes().getProjectVersion();
98 deletePreviousEventsHavingSameVersion(session, projectVersion, component);
99 dbClient.eventDao().insert(session, newBaseEvent(component, analysisDate)
100 .setName(projectVersion)
101 .setCategory(EventDto.CATEGORY_VERSION));
104 private void deletePreviousEventsHavingSameVersion(DbSession session, String version, Component component) {
105 for (EventDto dto : dbClient.eventDao().selectByComponentUuid(session, component.getUuid())) {
106 if (Objects.equals(dto.getCategory(), EventDto.CATEGORY_VERSION) && Objects.equals(dto.getName(), version)) {
107 dbClient.eventDao().delete(session, dto.getUuid());
112 private EventDto newBaseEvent(Component component, Long analysisDate) {
113 return new EventDto()
114 .setUuid(uuidFactory.create())
115 .setAnalysisUuid(analysisMetadataHolder.getUuid())
116 .setComponentUuid(component.getUuid())
117 .setCreatedAt(system2.now())
118 .setDate(analysisDate);
121 private String convertCategory(Event.Category category) {
122 return switch (category) {
123 case ALERT -> EventDto.CATEGORY_ALERT;
124 case PROFILE -> EventDto.CATEGORY_PROFILE;
125 case ISSUE_DETECTION -> EventDto.CATEGORY_ISSUE_DETECTION;