3 * Copyright (C) 2009-2020 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.Collectors;
25 import java.util.stream.StreamSupport;
26 import org.sonar.api.utils.System2;
27 import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
28 import org.sonar.ce.task.projectanalysis.component.Component;
29 import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit;
30 import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
31 import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
32 import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter;
33 import org.sonar.ce.task.projectanalysis.event.Event;
34 import org.sonar.ce.task.projectanalysis.event.EventRepository;
35 import org.sonar.ce.task.step.ComputationStep;
36 import org.sonar.core.util.UuidFactory;
37 import org.sonar.db.DbClient;
38 import org.sonar.db.DbSession;
39 import org.sonar.db.event.EventDto;
41 public class PersistEventsStep implements ComputationStep {
43 private final DbClient dbClient;
44 private final System2 system2;
45 private final AnalysisMetadataHolder analysisMetadataHolder;
46 private final TreeRootHolder treeRootHolder;
47 private final EventRepository eventRepository;
48 private final UuidFactory uuidFactory;
50 public PersistEventsStep(DbClient dbClient, System2 system2, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
51 EventRepository eventRepository, UuidFactory uuidFactory) {
52 this.dbClient = dbClient;
53 this.system2 = system2;
54 this.treeRootHolder = treeRootHolder;
55 this.analysisMetadataHolder = analysisMetadataHolder;
56 this.eventRepository = eventRepository;
57 this.uuidFactory = uuidFactory;
61 public void execute(ComputationStep.Context context) {
62 try (DbSession dbSession = dbClient.openSession(false)) {
63 long analysisDate = analysisMetadataHolder.getAnalysisDate();
64 new DepthTraversalTypeAwareCrawler(new PersistEventComponentVisitor(dbSession, analysisDate))
65 .visit(treeRootHolder.getRoot());
71 public String getDescription() {
72 return "Persist events";
75 private class PersistEventComponentVisitor extends TypeAwareVisitorAdapter {
76 private final DbSession session;
77 private final long analysisDate;
79 PersistEventComponentVisitor(DbSession session, long analysisDate) {
80 super(CrawlerDepthLimit.PROJECT, Order.PRE_ORDER);
81 this.session = session;
82 this.analysisDate = analysisDate;
86 public void visitProject(Component project) {
87 processEvents(session, project, analysisDate);
88 saveVersionEvent(session, project, analysisDate);
91 private void processEvents(DbSession session, Component component, Long analysisDate) {
92 Function<Event, EventDto> eventToEventDto = event -> newBaseEvent(component, analysisDate)
93 .setName(event.getName())
94 .setCategory(convertCategory(event.getCategory()))
95 .setDescription(event.getDescription())
96 .setData(event.getData());
98 for (EventDto batchEventDto : StreamSupport.stream(eventRepository.getEvents(component).spliterator(), false).map(eventToEventDto).collect(Collectors.toList())) {
99 dbClient.eventDao().insert(session, batchEventDto);
103 private void saveVersionEvent(DbSession session, Component component, Long analysisDate) {
104 String projectVersion = component.getProjectAttributes().getProjectVersion();
105 deletePreviousEventsHavingSameVersion(session, projectVersion, component);
106 dbClient.eventDao().insert(session, newBaseEvent(component, analysisDate)
107 .setName(projectVersion)
108 .setCategory(EventDto.CATEGORY_VERSION));
111 private void deletePreviousEventsHavingSameVersion(DbSession session, String version, Component component) {
112 for (EventDto dto : dbClient.eventDao().selectByComponentUuid(session, component.getUuid())) {
113 if (Objects.equals(dto.getCategory(), EventDto.CATEGORY_VERSION) && Objects.equals(dto.getName(), version)) {
114 dbClient.eventDao().delete(session, dto.getId());
119 private EventDto newBaseEvent(Component component, Long analysisDate) {
120 return new EventDto()
121 .setUuid(uuidFactory.create())
122 .setAnalysisUuid(analysisMetadataHolder.getUuid())
123 .setComponentUuid(component.getUuid())
124 .setCreatedAt(system2.now())
125 .setDate(analysisDate);
128 private String convertCategory(Event.Category category) {
131 return EventDto.CATEGORY_ALERT;
133 return EventDto.CATEGORY_PROFILE;
135 throw new IllegalArgumentException(String.format("Unsupported category %s", category.name()));