BlockServiceImpl.java

1
package org.cardanofoundation.explorer.api.service.impl;
2
3
import java.math.BigInteger;
4
import java.util.ArrayList;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.Objects;
8
import java.util.function.Function;
9
import java.util.stream.Collectors;
10
11
import lombok.RequiredArgsConstructor;
12
import lombok.extern.log4j.Log4j2;
13
14
import org.springframework.data.domain.*;
15
import org.springframework.data.domain.Sort.Direction;
16
import org.springframework.stereotype.Service;
17
18
import org.apache.commons.lang3.StringUtils;
19
20
import org.cardanofoundation.explorer.api.common.enumeration.BlockPropagationChartType;
21
import org.cardanofoundation.explorer.api.exception.BusinessCode;
22
import org.cardanofoundation.explorer.api.exception.NoContentException;
23
import org.cardanofoundation.explorer.api.mapper.BlockMapper;
24
import org.cardanofoundation.explorer.api.mapper.BlockPropagationMapper;
25
import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse;
26
import org.cardanofoundation.explorer.api.model.response.BlockFilterResponse;
27
import org.cardanofoundation.explorer.api.model.response.BlockPropagationResponse;
28
import org.cardanofoundation.explorer.api.model.response.BlockResponse;
29
import org.cardanofoundation.explorer.api.projection.PoolMintBlockProjection;
30
import org.cardanofoundation.explorer.api.repository.explorer.BlockStatisticsDailyRepository;
31
import org.cardanofoundation.explorer.api.repository.explorer.BlockStatisticsPerEpochRepository;
32
import org.cardanofoundation.explorer.api.repository.ledgersync.BlockRepository;
33
import org.cardanofoundation.explorer.api.repository.ledgersync.CustomBlockRepository;
34
import org.cardanofoundation.explorer.api.repository.ledgersync.SlotLeaderRepository;
35
import org.cardanofoundation.explorer.api.repository.ledgersync.TxRepository;
36
import org.cardanofoundation.explorer.api.service.BlockService;
37
import org.cardanofoundation.explorer.common.entity.ledgersync.BaseEntity;
38
import org.cardanofoundation.explorer.common.entity.ledgersync.BaseEntity_;
39
import org.cardanofoundation.explorer.common.entity.ledgersync.Block;
40
import org.cardanofoundation.explorer.common.entity.ledgersync.Block_;
41
import org.cardanofoundation.explorer.common.entity.ledgersync.SlotLeader;
42
import org.cardanofoundation.explorer.common.entity.ledgersync.Tx;
43
import org.cardanofoundation.explorer.common.exception.BusinessException;
44
45
@Service
46
@RequiredArgsConstructor
47
@Log4j2
48
public class BlockServiceImpl implements BlockService {
49
50
  private final BlockRepository blockRepository;
51
  private final TxRepository txRepository;
52
  private final SlotLeaderRepository slotLeaderRepository;
53
  private final BlockMapper blockMapper;
54
  private final CustomBlockRepository customBlockRepository;
55
  private final BlockStatisticsPerEpochRepository blockStatisticsPerEpochRepository;
56
  private final BlockStatisticsDailyRepository blockStatisticsDailyRepository;
57
  private final BlockPropagationMapper blockPropagationMapper;
58
59
  @Override
60
  public BlockResponse getBlockDetailByBlockId(String blockId) {
61
    try {
62
      Long blockNo = Long.parseLong(blockId);
63
      Block block =
64
          blockRepository
65
              .findFirstByBlockNo(blockNo)
66 1 1. lambda$getBlockDetailByBlockId$0 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$getBlockDetailByBlockId$0 → KILLED
              .orElseThrow(() -> new BusinessException(BusinessCode.BLOCK_NOT_FOUND));
67 1 1. getBlockDetailByBlockId : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockDetailByBlockId → KILLED
      return getBlockResponse(block);
68
    } catch (NumberFormatException e) {
69
      Block block =
70
          blockRepository
71
              .findFirstByHash(blockId)
72 1 1. lambda$getBlockDetailByBlockId$1 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$getBlockDetailByBlockId$1 → KILLED
              .orElseThrow(() -> new BusinessException(BusinessCode.BLOCK_NOT_FOUND));
73 1 1. getBlockDetailByBlockId : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockDetailByBlockId → KILLED
      return getBlockResponse(block);
74
    }
75
  }
76
77
  /**
78
   * Get block response from entity, calculate totalOutputs and total fees
79
   *
80
   * @param block block entity
81
   * @return block response
82
   */
83
  private BlockResponse getBlockResponse(Block block) {
84
    BlockResponse blockResponse = blockMapper.blockToBlockResponse(block);
85
    List<Tx> txList = txRepository.findAllByBlock(block);
86
    PoolMintBlockProjection poolMintBlockProjection =
87
        blockRepository.getPoolInfoThatMintedBlock(block.getBlockNo());
88 1 1. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setTotalOutput → SURVIVED
    blockResponse.setTotalOutput(
89
        txList.stream().map(Tx::getOutSum).reduce(BigInteger.ZERO, BigInteger::add));
90 1 1. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setTotalFees → SURVIVED
    blockResponse.setTotalFees(
91
        txList.stream().map(Tx::getFee).reduce(BigInteger.ZERO, BigInteger::add));
92
93 1 1. getBlockResponse : negated conditional → KILLED
    if (!Objects.isNull(poolMintBlockProjection)) {
94 1 1. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setPoolName → SURVIVED
      blockResponse.setPoolName(poolMintBlockProjection.getPoolName());
95 1 1. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setPoolView → KILLED
      blockResponse.setPoolView(poolMintBlockProjection.getPoolView());
96 1 1. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setPoolTicker → SURVIVED
      blockResponse.setPoolTicker(poolMintBlockProjection.getPoolTicker());
97 1 1. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setDescription → SURVIVED
      blockResponse.setDescription(poolMintBlockProjection.getDescription());
98
    }
99
100
    Integer currentBlockNo =
101
        blockRepository
102
            .findCurrentBlock()
103 1 1. lambda$getBlockResponse$2 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$getBlockResponse$2 → KILLED
            .orElseThrow(() -> new BusinessException(BusinessCode.BLOCK_NOT_FOUND));
104 1 1. getBlockResponse : negated conditional → KILLED
    if (Objects.nonNull(block.getBlockNo())) {
105 2 1. getBlockResponse : Replaced integer subtraction with addition → SURVIVED
2. getBlockResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setConfirmation → SURVIVED
      blockResponse.setConfirmation(currentBlockNo - block.getBlockNo().intValue());
106
    }
107 1 1. getBlockResponse : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockResponse → KILLED
    return blockResponse;
108
  }
109
110
  @Override
111
  public BaseFilterResponse<BlockFilterResponse> filterBlock(Pageable pageable) {
112
    long totalElements = blockRepository.countAllBlock();
113
    Direction direction = null;
114
    String sortField = null;
115 1 1. filterBlock : negated conditional → KILLED
    if (pageable.getSort().isSorted()) {
116
      direction = pageable.getSort().stream().findFirst().get().getDirection();
117
      sortField = pageable.getSort().stream().findFirst().get().getProperty();
118
    }
119
    Page<Block> blockPage;
120
121 2 1. filterBlock : negated conditional → KILLED
2. filterBlock : negated conditional → KILLED
    boolean sortFieldFlag = Block_.TIME.equals(sortField) || BaseEntity_.ID.equals(sortField);
122 2 1. filterBlock : negated conditional → SURVIVED
2. filterBlock : negated conditional → NO_COVERAGE
    if (Direction.ASC.equals(direction) && Boolean.TRUE.equals(sortFieldFlag)) {
123
      blockPage = getBlockFilterListByTimeAsc(pageable, totalElements);
124 2 1. filterBlock : negated conditional → SURVIVED
2. filterBlock : negated conditional → KILLED
    } else if ((Direction.DESC.equals(direction) && Boolean.TRUE.equals(sortFieldFlag))
125 1 1. filterBlock : negated conditional → KILLED
        || Objects.isNull(direction)
126 1 1. filterBlock : negated conditional → KILLED
        || StringUtils.isEmpty(sortField)) {
127
      blockPage = getBlockFilterListByTimeDesc(pageable, totalElements);
128
    } else {
129
      blockPage = blockRepository.findAllBlock(pageable);
130
    }
131 1 1. filterBlock : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::filterBlock → KILLED
    return mapperBlockToBlockFilterResponse(blockPage, false);
132
  }
133
134
  /**
135
   * Get block filter response order by time|id asc. Main idea: Find the first block id by page and
136
   * genesis|ebb block count. Then find the block list by first block id and limit.
137
   *
138
   * @param pageable
139
   * @param totalElements
140
   * @return block filter response
141
   */
142
  private Page<Block> getBlockFilterListByTimeAsc(Pageable pageable, long totalElements) {
143 1 1. getBlockFilterListByTimeAsc : Replaced long multiplication with division → NO_COVERAGE
    long firstBlockIndexOfPage = (long) pageable.getPageNumber() * pageable.getPageSize();
144
    long currentMaxBlockNo = blockRepository.findCurrentBlock().map(Long::valueOf).orElse(0L);
145
    long minBlockNo = blockRepository.findMinBlockNo();
146
    // if current max block no is less than first block index of page, then call
147
    // getBlocksAscByAFewPageAhead
148 2 1. getBlockFilterListByTimeAsc : negated conditional → NO_COVERAGE
2. getBlockFilterListByTimeAsc : changed conditional boundary → NO_COVERAGE
    if (currentMaxBlockNo < firstBlockIndexOfPage) {
149 1 1. getBlockFilterListByTimeAsc : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeAsc → NO_COVERAGE
      return getBlocksAscByAFewPageAhead(
150
          pageable, totalElements, firstBlockIndexOfPage, currentMaxBlockNo);
151
    }
152
    // if blockNo start from 0, then the first block index of page should minus 1
153 2 1. getBlockFilterListByTimeAsc : Replaced long subtraction with addition → NO_COVERAGE
2. getBlockFilterListByTimeAsc : negated conditional → NO_COVERAGE
    firstBlockIndexOfPage = firstBlockIndexOfPage - ((minBlockNo == 0) ? 1 : 0);
154
    // get first block id by first block no of page
155
    long firstBlockId =
156
        blockRepository.findFirstByBlockNo(firstBlockIndexOfPage).map(Block::getId).orElse(0L);
157
158
    // get genesis|ebb block count in front of first block id
159
    long ebbBlkCntInFrontOf =
160
        blockRepository.countGenesisAndEbbBlockInfoByBlockIdLessThan(firstBlockId).orElse(0L);
161
162
    long actualFirstBlockId;
163 2 1. getBlockFilterListByTimeAsc : negated conditional → NO_COVERAGE
2. getBlockFilterListByTimeAsc : changed conditional boundary → NO_COVERAGE
    if (ebbBlkCntInFrontOf > 0) {
164 2 1. getBlockFilterListByTimeAsc : Replaced long subtraction with addition → NO_COVERAGE
2. getBlockFilterListByTimeAsc : Replaced long addition with subtraction → NO_COVERAGE
      actualFirstBlockId =
165
          blockRepository
166
              .findFirstByBlockNo(firstBlockIndexOfPage - ebbBlkCntInFrontOf + 1)
167
              .map(Block::getId)
168
              .orElse(0L);
169
    } else {
170
      actualFirstBlockId = firstBlockId;
171
    }
172
173
    List<Block> blockList =
174
        getBlocksByBlockIdAndLimit(pageable.getPageSize(), actualFirstBlockId, Direction.ASC);
175
176 1 1. getBlockFilterListByTimeAsc : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeAsc → NO_COVERAGE
    return new PageImpl<>(blockList, pageable, totalElements);
177
  }
178
179
  /**
180
   * Get block filter response ASC, based on last block of a few page ahead. Main idea: Find the
181
   * last block of a few page ahead
182
   *
183
   * @param pageable
184
   * @param totalElements
185
   * @param firstBlockIndexOfPage
186
   * @param currentMaxBlockNo
187
   * @return
188
   */
189
  private Page<Block> getBlocksAscByAFewPageAhead(
190
      Pageable pageable, long totalElements, long firstBlockIndexOfPage, long currentMaxBlockNo) {
191 1 1. getBlocksAscByAFewPageAhead : Replaced long subtraction with addition → NO_COVERAGE
    int numberOfAFewPageAhead =
192 2 1. getBlocksAscByAFewPageAhead : Replaced integer division with multiplication → NO_COVERAGE
2. getBlocksAscByAFewPageAhead : Replaced integer addition with subtraction → NO_COVERAGE
        (int) (firstBlockIndexOfPage - currentMaxBlockNo) / pageable.getPageSize() + 1;
193
194
    Block lastBlockFromAFewPageAhead =
195
        getBlockFilterListByTimeAsc(
196
                PageRequest.of(
197 1 1. getBlocksAscByAFewPageAhead : Replaced integer subtraction with addition → NO_COVERAGE
                    pageable.getPageNumber() - numberOfAFewPageAhead,
198
                    pageable.getPageSize(),
199
                    Direction.ASC,
200
                    BaseEntity_.ID),
201
                totalElements)
202
            .getContent()
203 1 1. getBlocksAscByAFewPageAhead : Replaced integer subtraction with addition → NO_COVERAGE
            .get(pageable.getPageSize() - 1);
204
205
    long nextBlockId = blockRepository.findNextBlockId(lastBlockFromAFewPageAhead.getId());
206
207
    List<Block> blocksResponse =
208
        getBlocksByBlockIdAndLimit(
209 1 1. getBlocksAscByAFewPageAhead : Replaced integer multiplication with division → NO_COVERAGE
            numberOfAFewPageAhead * pageable.getPageSize(), nextBlockId, Direction.ASC);
210
211
    blocksResponse =
212
        blocksResponse.subList(
213 2 1. getBlocksAscByAFewPageAhead : Replaced integer subtraction with addition → NO_COVERAGE
2. getBlocksAscByAFewPageAhead : Replaced integer multiplication with division → NO_COVERAGE
            Math.min(blocksResponse.size(), (numberOfAFewPageAhead - 1) * pageable.getPageSize()),
214 1 1. getBlocksAscByAFewPageAhead : Replaced integer multiplication with division → NO_COVERAGE
            Math.min(blocksResponse.size(), numberOfAFewPageAhead * pageable.getPageSize()));
215
216 1 1. getBlocksAscByAFewPageAhead : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlocksAscByAFewPageAhead → NO_COVERAGE
    return new PageImpl<>(blocksResponse, pageable, totalElements);
217
  }
218
219
  private List<Block> getBlocksByBlockIdAndLimit(int limit, long blockId, Direction direction) {
220 1 1. getBlocksByBlockIdAndLimit : replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlocksByBlockIdAndLimit → NO_COVERAGE
    return customBlockRepository.findByBlockIdAndLimit(blockId, limit, direction);
221
  }
222
223
  /**
224
   * Get block filter response order by time|id desc. Main idea: Find the first block id by page and
225
   * genesis|ebb block count. Then find the block list by first block id and limit.
226
   *
227
   * @param pageable
228
   * @param totalElements
229
   * @return
230
   */
231
  private Page<Block> getBlockFilterListByTimeDesc(Pageable pageable, long totalElements) {
232
    long firstBlockIndexOfPage =
233 2 1. getBlockFilterListByTimeDesc : Replaced long subtraction with addition → NO_COVERAGE
2. getBlockFilterListByTimeDesc : Replaced long multiplication with division → NO_COVERAGE
        totalElements - (long) pageable.getPageNumber() * pageable.getPageSize();
234
235
    long currentMaxBlockNo = blockRepository.findCurrentBlock().map(Long::valueOf).orElse(0L);
236 2 1. getBlockFilterListByTimeDesc : negated conditional → NO_COVERAGE
2. getBlockFilterListByTimeDesc : changed conditional boundary → NO_COVERAGE
    if (firstBlockIndexOfPage > currentMaxBlockNo) {
237 1 1. getBlockFilterListByTimeDesc : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeDesc → NO_COVERAGE
      return getBlocksDescByFirstFewPage(pageable, totalElements, currentMaxBlockNo);
238
    }
239
240
    // get first block id by first block no of page
241
    long firstBlockId =
242
        blockRepository
243
            .findFirstByBlockNo(
244 2 1. getBlockFilterListByTimeDesc : Replaced long multiplication with division → NO_COVERAGE
2. getBlockFilterListByTimeDesc : Replaced long subtraction with addition → NO_COVERAGE
                currentMaxBlockNo - (long) pageable.getPageNumber() * pageable.getPageSize())
245
            .map(Block::getId)
246
            .orElse(0L);
247
248
    // get total genesis|ebb block count
249
    long totalGenesisAndEbbBlockCnt =
250
        blockRepository.countGenesisAndEbbBlockInfoByBlockIdGreaterThan(0L).orElse(0L);
251
252
    // get genesis|ebb block count behind first block id
253
    long ebbBlkCntBehind =
254
        blockRepository.countGenesisAndEbbBlockInfoByBlockIdGreaterThan(firstBlockId).orElse(0L);
255
256
    // get actualFirstBlockId
257
    long actualFirstBlockId;
258 2 1. getBlockFilterListByTimeDesc : changed conditional boundary → NO_COVERAGE
2. getBlockFilterListByTimeDesc : negated conditional → NO_COVERAGE
    if (ebbBlkCntBehind > 0) {
259 2 1. getBlockFilterListByTimeDesc : Replaced long subtraction with addition → NO_COVERAGE
2. getBlockFilterListByTimeDesc : Replaced long subtraction with addition → NO_COVERAGE
      actualFirstBlockId =
260
          blockRepository
261
              .findFirstByBlockNo(
262
                  firstBlockIndexOfPage - (totalGenesisAndEbbBlockCnt - ebbBlkCntBehind))
263
              .map(Block::getId)
264
              .orElse(0L);
265
    } else {
266
      actualFirstBlockId = firstBlockId;
267
    }
268
269
    List<Block> blockList =
270
        customBlockRepository.findByBlockIdAndLimit(
271
            actualFirstBlockId, pageable.getPageSize(), Direction.DESC);
272
273 1 1. getBlockFilterListByTimeDesc : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeDesc → NO_COVERAGE
    return new PageImpl<>(blockList, pageable, totalElements);
274
  }
275
276
  /**
277
   * Get block filter response DESC, based on first block of first few pages.
278
   *
279
   * @param pageable
280
   * @param totalElements
281
   * @param currentMaxBlockNo
282
   * @return
283
   */
284
  private PageImpl<Block> getBlocksDescByFirstFewPage(
285
      Pageable pageable, long totalElements, long currentMaxBlockNo) {
286
    long currentMaxBlockId =
287
        blockRepository.findFirstByBlockNo(currentMaxBlockNo).map(Block::getId).orElse(0L);
288
289
    List<Block> blocksResponse =
290
        getBlocksByBlockIdAndLimit(
291 2 1. getBlocksDescByFirstFewPage : Replaced integer addition with subtraction → NO_COVERAGE
2. getBlocksDescByFirstFewPage : Replaced integer multiplication with division → NO_COVERAGE
            (pageable.getPageNumber() + 1) * pageable.getPageSize(),
292
            currentMaxBlockId,
293
            Direction.DESC);
294
295
    blocksResponse =
296
        blocksResponse.subList(
297 1 1. getBlocksDescByFirstFewPage : Replaced integer multiplication with division → NO_COVERAGE
            Math.min(blocksResponse.size(), pageable.getPageNumber() * pageable.getPageSize()),
298
            Math.min(
299 2 1. getBlocksDescByFirstFewPage : Replaced integer addition with subtraction → NO_COVERAGE
2. getBlocksDescByFirstFewPage : Replaced integer multiplication with division → NO_COVERAGE
                blocksResponse.size(), (pageable.getPageNumber() + 1) * pageable.getPageSize()));
300
301 1 1. getBlocksDescByFirstFewPage : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlocksDescByFirstFewPage → NO_COVERAGE
    return new PageImpl<>(blocksResponse, pageable, totalElements);
302
  }
303
304
  @Override
305
  public BaseFilterResponse<BlockFilterResponse> getBlockByEpoch(String no, Pageable pageable) {
306
    try {
307
      Integer epochNo = Integer.parseInt(no);
308
      Page<Block> blocks = blockRepository.findBlockByEpochNo(epochNo, pageable);
309 1 1. getBlockByEpoch : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockByEpoch → KILLED
      return mapperBlockToBlockFilterResponse(blocks, false);
310
    } catch (NumberFormatException e) {
311
      throw new NoContentException(BusinessCode.EPOCH_NOT_FOUND);
312
    }
313
  }
314
315
  @Override
316
  public List<BlockPropagationResponse> getBlockPropagation(
317
      BlockPropagationChartType type, Pageable pageable) {
318
    // if type is null, will get block statistics per epoch as default
319 2 1. getBlockPropagation : negated conditional → NO_COVERAGE
2. getBlockPropagation : negated conditional → NO_COVERAGE
    if (type == null || type.equals(BlockPropagationChartType.EPOCH)) {
320 1 1. getBlockPropagation : replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockPropagation → NO_COVERAGE
      return blockStatisticsPerEpochRepository.findBlockPropagation(pageable).stream()
321
          .map(blockPropagationMapper::fromBlockPropagationProjection)
322
          .collect(Collectors.toList());
323
    } else {
324 1 1. getBlockPropagation : replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockPropagation → NO_COVERAGE
      return blockStatisticsDailyRepository.findBlockPropagation(pageable).stream()
325
          .map(blockPropagationMapper::fromBlockPropagationProjection)
326
          .collect(Collectors.toList());
327
    }
328
  }
329
330
  /**
331
   * Mapping from block entity to block response dto
332
   *
333
   * @param blocks list block entity
334
   * @return list block information in this page
335
   */
336
  private BaseFilterResponse<BlockFilterResponse> mapperBlockToBlockFilterResponse(
337
      Page<Block> blocks, boolean isGetAllBlock) {
338
    // get slot leader for block
339
    List<SlotLeader> slotLeaders =
340
        slotLeaderRepository.findByIdIn(
341
            blocks.getContent().stream().map(Block::getSlotLeaderId).collect(Collectors.toList()));
342
    Map<Long, SlotLeader> slotLeaderMap =
343
        slotLeaders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));
344
345
    List<Tx> txList = txRepository.findByBlockIn(blocks.toList());
346
347
    // create map with key: block_id, value : total output of block
348
    Map<Long, BigInteger> blockTotalOutputMap =
349
        txList.stream()
350
            .collect(
351
                Collectors.groupingBy(
352 1 1. lambda$mapperBlockToBlockFilterResponse$3 : replaced Long return value with 0L for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$mapperBlockToBlockFilterResponse$3 → SURVIVED
                    tx -> tx.getBlock().getId(),
353
                    Collectors.reducing(BigInteger.ZERO, Tx::getOutSum, BigInteger::add)));
354
    // create map with key: block_id, value : total fee of block
355
    Map<Long, BigInteger> blockTotalFeeMap =
356
        txList.stream()
357
            .collect(
358
                Collectors.groupingBy(
359 1 1. lambda$mapperBlockToBlockFilterResponse$4 : replaced Long return value with 0L for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$mapperBlockToBlockFilterResponse$4 → SURVIVED
                    tx -> tx.getBlock().getId(),
360
                    Collectors.reducing(BigInteger.ZERO, Tx::getFee, BigInteger::add)));
361
362
    List<BlockFilterResponse> blockFilterResponseList = new ArrayList<>();
363
364
    for (Block block : blocks) {
365 1 1. mapperBlockToBlockFilterResponse : removed call to org/cardanofoundation/explorer/common/entity/ledgersync/Block::setSlotLeader → SURVIVED
      block.setSlotLeader(slotLeaderMap.get(block.getSlotLeaderId()));
366
      BlockFilterResponse blockResponse = blockMapper.blockToBlockFilterResponse(block);
367 1 1. mapperBlockToBlockFilterResponse : negated conditional → SURVIVED
      if (!isGetAllBlock) {
368
        var totalOutput = blockTotalOutputMap.get(block.getId());
369
        var totalFees = blockTotalFeeMap.get(block.getId());
370 1 1. mapperBlockToBlockFilterResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockFilterResponse::setTotalOutput → SURVIVED
        blockResponse.setTotalOutput(Objects.requireNonNullElse(totalOutput, BigInteger.ZERO));
371 1 1. mapperBlockToBlockFilterResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockFilterResponse::setTotalFees → SURVIVED
        blockResponse.setTotalFees(Objects.requireNonNullElse(totalFees, BigInteger.ZERO));
372
      } else {
373 1 1. mapperBlockToBlockFilterResponse : removed call to org/cardanofoundation/explorer/api/model/response/BlockFilterResponse::setTxCount → NO_COVERAGE
        blockResponse.setTxCount(null);
374
      }
375
      blockFilterResponseList.add(blockResponse);
376
    }
377 1 1. mapperBlockToBlockFilterResponse : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::mapperBlockToBlockFilterResponse → KILLED
    return new BaseFilterResponse<>(blocks, blockFilterResponseList);
378
  }
379
}

Mutations

66

1.1
Location : lambda$getBlockDetailByBlockId$0
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockNoNotFound()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$getBlockDetailByBlockId$0 → KILLED

67

1.1
Location : getBlockDetailByBlockId
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockNoExists()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockDetailByBlockId → KILLED

72

1.1
Location : lambda$getBlockDetailByBlockId$1
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockHashNotFound()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$getBlockDetailByBlockId$1 → KILLED

73

1.1
Location : getBlockDetailByBlockId
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockHashExists()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockDetailByBlockId → KILLED

88

1.1
Location : getBlockResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setTotalOutput → SURVIVED

90

1.1
Location : getBlockResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setTotalFees → SURVIVED

93

1.1
Location : getBlockResponse
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockHashExists()]
negated conditional → KILLED

94

1.1
Location : getBlockResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setPoolName → SURVIVED

95

1.1
Location : getBlockResponse
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockHashExists()]
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setPoolView → KILLED

96

1.1
Location : getBlockResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setPoolTicker → SURVIVED

97

1.1
Location : getBlockResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setDescription → SURVIVED

103

1.1
Location : lambda$getBlockResponse$2
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_ThrowCurrentBlock()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$getBlockResponse$2 → KILLED

104

1.1
Location : getBlockResponse
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockHashExists()]
negated conditional → KILLED

105

1.1
Location : getBlockResponse
Killed by : none
Replaced integer subtraction with addition → SURVIVED

2.2
Location : getBlockResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockResponse::setConfirmation → SURVIVED

107

1.1
Location : getBlockResponse
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockDetailByBlockId_WhenBlockNoExists()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockResponse → KILLED

115

1.1
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
negated conditional → KILLED

121

1.1
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
negated conditional → KILLED

2.2
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
negated conditional → KILLED

122

1.1
Location : filterBlock
Killed by : none
negated conditional → SURVIVED

2.2
Location : filterBlock
Killed by : none
negated conditional → NO_COVERAGE

124

1.1
Location : filterBlock
Killed by : none
negated conditional → SURVIVED

2.2
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
negated conditional → KILLED

125

1.1
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
negated conditional → KILLED

126

1.1
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
negated conditional → KILLED

131

1.1
Location : filterBlock
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testFilterBlock()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::filterBlock → KILLED

143

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
Replaced long multiplication with division → NO_COVERAGE

148

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeAsc
Killed by : none
changed conditional boundary → NO_COVERAGE

149

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeAsc → NO_COVERAGE

153

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeAsc
Killed by : none
negated conditional → NO_COVERAGE

163

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeAsc
Killed by : none
changed conditional boundary → NO_COVERAGE

164

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeAsc
Killed by : none
Replaced long addition with subtraction → NO_COVERAGE

176

1.1
Location : getBlockFilterListByTimeAsc
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeAsc → NO_COVERAGE

191

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

192

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer division with multiplication → NO_COVERAGE

2.2
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

197

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

203

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

209

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

213

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

2.2
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

214

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

216

1.1
Location : getBlocksAscByAFewPageAhead
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlocksAscByAFewPageAhead → NO_COVERAGE

220

1.1
Location : getBlocksByBlockIdAndLimit
Killed by : none
replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlocksByBlockIdAndLimit → NO_COVERAGE

233

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeDesc
Killed by : none
Replaced long multiplication with division → NO_COVERAGE

236

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeDesc
Killed by : none
changed conditional boundary → NO_COVERAGE

237

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeDesc → NO_COVERAGE

244

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
Replaced long multiplication with division → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeDesc
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

258

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeDesc
Killed by : none
negated conditional → NO_COVERAGE

259

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

2.2
Location : getBlockFilterListByTimeDesc
Killed by : none
Replaced long subtraction with addition → NO_COVERAGE

273

1.1
Location : getBlockFilterListByTimeDesc
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockFilterListByTimeDesc → NO_COVERAGE

291

1.1
Location : getBlocksDescByFirstFewPage
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

2.2
Location : getBlocksDescByFirstFewPage
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

297

1.1
Location : getBlocksDescByFirstFewPage
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

299

1.1
Location : getBlocksDescByFirstFewPage
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

2.2
Location : getBlocksDescByFirstFewPage
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

301

1.1
Location : getBlocksDescByFirstFewPage
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlocksDescByFirstFewPage → NO_COVERAGE

309

1.1
Location : getBlockByEpoch
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockByEpoch_WhenEpochNoExists()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockByEpoch → KILLED

319

1.1
Location : getBlockPropagation
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : getBlockPropagation
Killed by : none
negated conditional → NO_COVERAGE

320

1.1
Location : getBlockPropagation
Killed by : none
replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockPropagation → NO_COVERAGE

324

1.1
Location : getBlockPropagation
Killed by : none
replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::getBlockPropagation → NO_COVERAGE

352

1.1
Location : lambda$mapperBlockToBlockFilterResponse$3
Killed by : none
replaced Long return value with 0L for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$mapperBlockToBlockFilterResponse$3 → SURVIVED

359

1.1
Location : lambda$mapperBlockToBlockFilterResponse$4
Killed by : none
replaced Long return value with 0L for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::lambda$mapperBlockToBlockFilterResponse$4 → SURVIVED

365

1.1
Location : mapperBlockToBlockFilterResponse
Killed by : none
removed call to org/cardanofoundation/explorer/common/entity/ledgersync/Block::setSlotLeader → SURVIVED

367

1.1
Location : mapperBlockToBlockFilterResponse
Killed by : none
negated conditional → SURVIVED

370

1.1
Location : mapperBlockToBlockFilterResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockFilterResponse::setTotalOutput → SURVIVED

371

1.1
Location : mapperBlockToBlockFilterResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockFilterResponse::setTotalFees → SURVIVED

373

1.1
Location : mapperBlockToBlockFilterResponse
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/BlockFilterResponse::setTxCount → NO_COVERAGE

377

1.1
Location : mapperBlockToBlockFilterResponse
Killed by : org.cardanofoundation.explorer.api.service.BlockServiceTest.[engine:junit-jupiter]/[class:org.cardanofoundation.explorer.api.service.BlockServiceTest]/[method:testGetBlockByEpoch_WhenEpochNoExists()]
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BlockServiceImpl::mapperBlockToBlockFilterResponse → KILLED

Active mutators

Tests examined


Report generated by PIT 1.14.2