1 | package org.cardanofoundation.explorer.api.service.impl; | |
2 | ||
3 | import static org.cardanofoundation.explorer.api.service.impl.ReportHistoryServiceImpl.MIN_TIME; | |
4 | ||
5 | import java.io.ByteArrayInputStream; | |
6 | import java.sql.Timestamp; | |
7 | import java.time.Duration; | |
8 | import java.time.Instant; | |
9 | import java.time.LocalDateTime; | |
10 | import java.time.ZoneOffset; | |
11 | import java.time.temporal.ValueRange; | |
12 | import java.util.ArrayList; | |
13 | import java.util.List; | |
14 | import java.util.Objects; | |
15 | import java.util.Set; | |
16 | ||
17 | import lombok.RequiredArgsConstructor; | |
18 | import lombok.extern.log4j.Log4j2; | |
19 | ||
20 | import org.springframework.data.domain.*; | |
21 | import org.springframework.stereotype.Service; | |
22 | import org.springframework.transaction.annotation.Transactional; | |
23 | ||
24 | import org.cardanofoundation.explorer.api.common.constant.CommonConstant; | |
25 | import org.cardanofoundation.explorer.api.common.enumeration.ExportType; | |
26 | import org.cardanofoundation.explorer.api.exception.BusinessCode; | |
27 | import org.cardanofoundation.explorer.api.interceptor.auth.UserPrincipal; | |
28 | import org.cardanofoundation.explorer.api.model.request.pool.report.PoolReportCreateRequest; | |
29 | import org.cardanofoundation.explorer.api.model.request.stake.report.ReportHistoryFilterRequest; | |
30 | import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse; | |
31 | import org.cardanofoundation.explorer.api.model.response.pool.lifecycle.DeRegistrationResponse; | |
32 | import org.cardanofoundation.explorer.api.model.response.pool.lifecycle.PoolUpdateDetailResponse; | |
33 | import org.cardanofoundation.explorer.api.model.response.pool.lifecycle.RewardResponse; | |
34 | import org.cardanofoundation.explorer.api.model.response.pool.lifecycle.TabularRegisResponse; | |
35 | import org.cardanofoundation.explorer.api.model.response.pool.projection.PoolHistoryKoiosProjection; | |
36 | import org.cardanofoundation.explorer.api.model.response.pool.report.PoolReportDetailResponse; | |
37 | import org.cardanofoundation.explorer.api.model.response.pool.report.PoolReportExportResponse; | |
38 | import org.cardanofoundation.explorer.api.model.response.pool.report.PoolReportListResponse; | |
39 | import org.cardanofoundation.explorer.api.repository.explorer.PoolReportRepository; | |
40 | import org.cardanofoundation.explorer.api.repository.ledgersync.PoolHashRepository; | |
41 | import org.cardanofoundation.explorer.api.repository.ledgersync.PoolHistoryRepository; | |
42 | import org.cardanofoundation.explorer.api.service.*; | |
43 | import org.cardanofoundation.explorer.api.util.DataUtil; | |
44 | import org.cardanofoundation.explorer.common.entity.enumeration.ReportStatus; | |
45 | import org.cardanofoundation.explorer.common.entity.enumeration.ReportType; | |
46 | import org.cardanofoundation.explorer.common.entity.explorer.PoolReportHistory; | |
47 | import org.cardanofoundation.explorer.common.entity.explorer.ReportHistory; | |
48 | import org.cardanofoundation.explorer.common.exception.BusinessException; | |
49 | ||
50 | @Service | |
51 | @RequiredArgsConstructor | |
52 | @Log4j2 | |
53 | public class PoolReportServiceImpl implements PoolReportService { | |
54 | ||
55 | private final PoolReportRepository poolReportRepository; | |
56 | ||
57 | private final StorageService storageService; | |
58 | ||
59 | private final PoolLifecycleService poolLifecycleService; | |
60 | ||
61 | private final PoolHashRepository poolHashRepository; | |
62 | ||
63 | private final FetchRewardDataService fetchRewardDataService; | |
64 | ||
65 | private final PoolHistoryRepository poolHistoryRepository; | |
66 | ||
67 | private final ReportHistoryService reportHistoryService; | |
68 | ||
69 | private final RoleService roleService; | |
70 | ||
71 | @Override | |
72 | @Transactional | |
73 | public Boolean create( | |
74 | PoolReportCreateRequest poolReportCreateRequest, UserPrincipal userPrincipal) { | |
75 | poolHashRepository | |
76 | .findByViewOrHashRaw(poolReportCreateRequest.getPoolId()) | |
77 |
1
1. lambda$create$0 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::lambda$create$0 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.POOL_NOT_FOUND)); |
78 | int reportLimit = roleService.getReportLimit(userPrincipal.getRoleDescription()); | |
79 |
1
1. create : negated conditional → KILLED |
if (reportLimit != CommonConstant.UNLIMITED_REPORT) { // "-1" it's mean unlimited report |
80 |
1
1. create : negated conditional → KILLED |
if (Boolean.TRUE.equals( |
81 | reportHistoryService.isLimitReached(userPrincipal.getUsername(), reportLimit))) { | |
82 | throw new BusinessException(BusinessCode.REPORT_LIMIT_REACHED); | |
83 | } | |
84 | } | |
85 | try { | |
86 | ReportHistory reportHistory = | |
87 | initReportHistory(poolReportCreateRequest, userPrincipal.getUsername()); | |
88 | poolReportRepository.saveAndFlush(poolReportCreateRequest.toEntity(reportHistory)); | |
89 |
1
1. create : replaced Boolean return with False for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::create → KILLED |
return true; |
90 | } catch (Exception e) { | |
91 | throw new BusinessException(BusinessCode.CREATE_REPORT_ERROR); | |
92 | } | |
93 | } | |
94 | ||
95 | @Override | |
96 | public PoolReportExportResponse export(Long reportId, ExportType exportType, String username) { | |
97 |
1
1. export : negated conditional → KILLED |
if (!ExportType.EXCEL.equals(exportType)) { |
98 | throw new BusinessException(BusinessCode.EXPORT_TYPE_NOT_SUPPORTED); | |
99 | } | |
100 | ||
101 | PoolReportHistory poolReport = getPoolReportHistory(reportId, username); | |
102 | String storageKey = poolReport.getReportHistory().getStorageKey(); | |
103 | String reportName = poolReport.getReportHistory().getReportName(); | |
104 | ReportStatus reportStatus = poolReport.getReportHistory().getStatus(); | |
105 | ||
106 |
2
1. export : negated conditional → KILLED 2. export : negated conditional → KILLED |
if (DataUtil.isNullOrEmpty(storageKey) || ReportStatus.IN_PROGRESS.equals(reportStatus)) { |
107 | throw new BusinessException(BusinessCode.REPORT_IS_IN_PROGRESS); | |
108 | } else { | |
109 | byte[] bytes = storageService.downloadFile(storageKey + exportType.getValue()); | |
110 |
1
1. export : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::export → KILLED |
return PoolReportExportResponse.builder() |
111 | .fileName(reportName + exportType.getValue()) | |
112 | .byteArrayInputStream(new ByteArrayInputStream(bytes)) | |
113 | .build(); | |
114 | } | |
115 | } | |
116 | ||
117 | @Override | |
118 | public BaseFilterResponse<PoolReportListResponse> list( | |
119 | Pageable pageable, String username, ReportHistoryFilterRequest filterRequest) { | |
120 | ||
121 | Timestamp timeAt7DayAgo = new Timestamp(Instant.now().minus(Duration.ofDays(7)).toEpochMilli()); | |
122 | String reportName = DataUtil.makeLikeQuery(filterRequest.getReportName()); | |
123 | Timestamp fromDate = Timestamp.valueOf(MIN_TIME); | |
124 | Timestamp toDate = Timestamp.from(Instant.now()); | |
125 |
1
1. list : negated conditional → KILLED |
if (!DataUtil.isNullOrEmpty(filterRequest.getFromDate())) { |
126 | fromDate = Timestamp.from(filterRequest.getFromDate().toInstant()); | |
127 | } | |
128 |
1
1. list : negated conditional → KILLED |
if (!DataUtil.isNullOrEmpty(filterRequest.getToDate())) { |
129 | toDate = Timestamp.from(filterRequest.getToDate().toInstant()); | |
130 | } | |
131 | ||
132 | Page<PoolReportHistory> poolReportPage = | |
133 | poolReportRepository.getPoolReportHistoryByFilter( | |
134 | reportName, fromDate, toDate, username, pageable); | |
135 | List<PoolReportHistory> poolReports = poolReportPage.getContent(); | |
136 | List<PoolReportListResponse> poolReportListResponses = | |
137 | poolReports.stream() | |
138 | .map( | |
139 | poolReportHistory -> { | |
140 | PoolReportListResponse response = | |
141 | PoolReportListResponse.toDomain(poolReportHistory); | |
142 | ||
143 |
1
1. lambda$list$1 : negated conditional → KILLED |
if (response.getCreatedAt().before(timeAt7DayAgo)) { |
144 |
1
1. lambda$list$1 : removed call to org/cardanofoundation/explorer/api/model/response/pool/report/PoolReportListResponse::setStatus → NO_COVERAGE |
response.setStatus(ReportStatus.EXPIRED); |
145 | } | |
146 |
1
1. lambda$list$1 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::lambda$list$1 → KILLED |
return response; |
147 | }) | |
148 | .toList(); | |
149 |
1
1. list : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::list → KILLED |
return new BaseFilterResponse<>(poolReportPage, poolReportListResponses); |
150 | } | |
151 | ||
152 | @Override | |
153 | public PoolReportHistory detail(Long reportId, String username) { | |
154 |
1
1. detail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::detail → KILLED |
return getPoolReportHistory(reportId, username); |
155 | } | |
156 | ||
157 | @Override | |
158 | public BaseFilterResponse<PoolReportDetailResponse.EpochSize> fetchEpochSize( | |
159 | Long reportId, Pageable pageable, String username) { | |
160 | PoolReportHistory poolReport = getPoolReportHistory(reportId, username); | |
161 | ||
162 | boolean useKoios = fetchRewardDataService.useKoios(); | |
163 |
1
1. fetchEpochSize : negated conditional → KILLED |
if (useKoios) { |
164 | Set<String> poolReportSet = Set.of(poolReport.getPoolView()); | |
165 | boolean isHistory = fetchRewardDataService.checkPoolHistoryForPool(poolReportSet); | |
166 | List<PoolHistoryKoiosProjection> poolHistoryProjections = new ArrayList<>(); | |
167 |
1
1. fetchEpochSize : negated conditional → KILLED |
if (!isHistory) { |
168 | boolean isFetch = | |
169 | fetchRewardDataService.fetchPoolHistoryForPool(Set.of(poolReport.getPoolView())); | |
170 |
1
1. fetchEpochSize : negated conditional → KILLED |
if (isFetch) { |
171 | poolHistoryProjections = | |
172 | poolHistoryRepository.getPoolHistoryKoios(poolReport.getPoolView()); | |
173 | } | |
174 | } else { | |
175 | poolHistoryProjections = | |
176 | poolHistoryRepository.getPoolHistoryKoios(poolReport.getPoolView()); | |
177 | } | |
178 | ||
179 |
1
1. fetchEpochSize : negated conditional → KILLED |
if (Objects.nonNull(poolHistoryProjections)) { |
180 | List<PoolReportDetailResponse.EpochSize> epochSizeList = | |
181 | poolHistoryProjections.stream() | |
182 | .filter( | |
183 | t -> | |
184 |
2
1. lambda$fetchEpochSize$2 : replaced boolean return with true for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::lambda$fetchEpochSize$2 → SURVIVED 2. lambda$fetchEpochSize$2 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::lambda$fetchEpochSize$2 → KILLED |
ValueRange.of(poolReport.getBeginEpoch(), poolReport.getEndEpoch()) |
185 | .isValidIntValue(t.getEpochNo())) | |
186 | .map(PoolReportDetailResponse.EpochSize::toDomain) | |
187 | .toList(); | |
188 |
1
1. fetchEpochSize : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchEpochSize → KILLED |
return new BaseFilterResponse<>(this.convertListToPage(epochSizeList, pageable)); |
189 | } else { | |
190 |
1
1. fetchEpochSize : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchEpochSize → NO_COVERAGE |
return new BaseFilterResponse<>(); |
191 | } | |
192 | ||
193 | } else { | |
194 |
1
1. fetchEpochSize : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchEpochSize → KILLED |
return new BaseFilterResponse<>(); |
195 | } | |
196 | } | |
197 | ||
198 | private Page<PoolReportDetailResponse.EpochSize> convertListToPage( | |
199 | List<PoolReportDetailResponse.EpochSize> list, Pageable pageable) { | |
200 |
1
1. convertListToPage : Replaced integer multiplication with division → SURVIVED |
int startIndex = pageable.getPageNumber() * pageable.getPageSize(); |
201 |
1
1. convertListToPage : Replaced integer addition with subtraction → KILLED |
int endIndex = Math.min(startIndex + pageable.getPageSize(), list.size()); |
202 | try { | |
203 | List<PoolReportDetailResponse.EpochSize> sublist = list.subList(startIndex, endIndex); | |
204 | PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize()); | |
205 |
1
1. convertListToPage : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::convertListToPage → KILLED |
return new PageImpl<>(sublist, pageRequest, list.size()); |
206 | } catch (Exception e) { | |
207 |
1
1. convertListToPage : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::convertListToPage → NO_COVERAGE |
return new PageImpl<>(new ArrayList<>()); |
208 | } | |
209 | } | |
210 | ||
211 | @Override | |
212 | public BaseFilterResponse<TabularRegisResponse> fetchPoolRegistration( | |
213 | Long reportId, Pageable pageable, String username) { | |
214 | PoolReportHistory poolReport = getPoolReportHistory(reportId, username); | |
215 |
1
1. fetchPoolRegistration : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchPoolRegistration → KILLED |
return poolLifecycleService.registrationList(poolReport.getPoolView(), pageable); |
216 | } | |
217 | ||
218 | @Override | |
219 | public BaseFilterResponse<PoolUpdateDetailResponse> fetchPoolUpdate( | |
220 | Long reportId, Pageable pageable, String username) { | |
221 | PoolReportHistory poolReport = getPoolReportHistory(reportId, username); | |
222 |
1
1. fetchPoolUpdate : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchPoolUpdate → KILLED |
return poolLifecycleService.poolUpdateList(poolReport.getPoolView(), pageable); |
223 | } | |
224 | ||
225 | @Override | |
226 | public BaseFilterResponse<RewardResponse> fetchRewardsDistribution( | |
227 | Long reportId, Pageable pageable, String username) { | |
228 | PoolReportHistory poolReport = getPoolReportHistory(reportId, username); | |
229 |
1
1. fetchRewardsDistribution : negated conditional → KILLED |
if (Boolean.FALSE.equals(fetchRewardDataService.useKoios())) { |
230 |
1
1. fetchRewardsDistribution : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchRewardsDistribution → NO_COVERAGE |
return new BaseFilterResponse<>(); |
231 | } | |
232 | ||
233 |
1
1. fetchRewardsDistribution : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchRewardsDistribution → KILLED |
return poolLifecycleService.listRewardFilter( |
234 | poolReport.getPoolView(), poolReport.getBeginEpoch(), poolReport.getEndEpoch(), pageable); | |
235 | } | |
236 | ||
237 | @Override | |
238 | public BaseFilterResponse<DeRegistrationResponse> fetchDeregistraion( | |
239 | Long reportId, Pageable pageable, String username) { | |
240 | PoolReportHistory poolReport = getPoolReportHistory(reportId, username); | |
241 |
1
1. fetchDeregistraion : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::fetchDeregistraion → KILLED |
return poolLifecycleService.deRegistration( |
242 | poolReport.getPoolView(), null, null, null, pageable); | |
243 | } | |
244 | ||
245 | private PoolReportHistory getPoolReportHistory(Long reportId, String username) { | |
246 | PoolReportHistory poolReportHistory = | |
247 | poolReportRepository | |
248 | .findById(reportId) | |
249 |
1
1. lambda$getPoolReportHistory$3 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::lambda$getPoolReportHistory$3 → NO_COVERAGE |
.orElseThrow(() -> new BusinessException(BusinessCode.POOL_REPORT_HISTORY_NOT_FOUND)); |
250 | ||
251 |
1
1. getPoolReportHistory : negated conditional → KILLED |
if (DataUtil.isNullOrEmpty(username) |
252 |
1
1. getPoolReportHistory : negated conditional → KILLED |
|| !username.equals(poolReportHistory.getReportHistory().getUsername())) { |
253 | throw new BusinessException(BusinessCode.POOL_REPORT_HISTORY_NOT_FOUND); | |
254 | } | |
255 |
1
1. getPoolReportHistory : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::getPoolReportHistory → KILLED |
return poolReportHistory; |
256 | } | |
257 | ||
258 | private ReportHistory initReportHistory( | |
259 | PoolReportCreateRequest poolReportCreateRequest, String username) { | |
260 |
1
1. initReportHistory : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::initReportHistory → SURVIVED |
return ReportHistory.builder() |
261 | .reportName( | |
262 |
1
1. initReportHistory : negated conditional → SURVIVED |
DataUtil.isNullOrEmpty(poolReportCreateRequest.getReportName()) |
263 | ? generateReportName(poolReportCreateRequest) | |
264 | : poolReportCreateRequest.getReportName()) | |
265 | .status(ReportStatus.IN_PROGRESS) | |
266 | .type(ReportType.POOL_ID) | |
267 | .username(username) | |
268 | .createdAt(Timestamp.valueOf(LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC))) | |
269 | .timePattern(poolReportCreateRequest.getTimePattern()) | |
270 | .dateFormat(poolReportCreateRequest.getDateFormat()) | |
271 | .zoneOffset(poolReportCreateRequest.getZoneOffset()) | |
272 | .build(); | |
273 | } | |
274 | ||
275 | private String generateReportName(PoolReportCreateRequest poolReportCreateRequest) { | |
276 |
1
1. generateReportName : replaced return value with "" for org/cardanofoundation/explorer/api/service/impl/PoolReportServiceImpl::generateReportName → SURVIVED |
return "report_pool_" |
277 | + poolReportCreateRequest.getPoolId() | |
278 | + "_" | |
279 | + poolReportCreateRequest.getEpochRanges()[0] | |
280 | + "_" | |
281 | + poolReportCreateRequest.getEpochRanges()[1]; | |
282 | } | |
283 | } | |
Mutations | ||
77 |
1.1 |
|
79 |
1.1 |
|
80 |
1.1 |
|
89 |
1.1 |
|
97 |
1.1 |
|
106 |
1.1 2.2 |
|
110 |
1.1 |
|
125 |
1.1 |
|
128 |
1.1 |
|
143 |
1.1 |
|
144 |
1.1 |
|
146 |
1.1 |
|
149 |
1.1 |
|
154 |
1.1 |
|
163 |
1.1 |
|
167 |
1.1 |
|
170 |
1.1 |
|
179 |
1.1 |
|
184 |
1.1 2.2 |
|
188 |
1.1 |
|
190 |
1.1 |
|
194 |
1.1 |
|
200 |
1.1 |
|
201 |
1.1 |
|
205 |
1.1 |
|
207 |
1.1 |
|
215 |
1.1 |
|
222 |
1.1 |
|
229 |
1.1 |
|
230 |
1.1 |
|
233 |
1.1 |
|
241 |
1.1 |
|
249 |
1.1 |
|
251 |
1.1 |
|
252 |
1.1 |
|
255 |
1.1 |
|
260 |
1.1 |
|
262 |
1.1 |
|
276 |
1.1 |