CCommitteeServiceImpl.java

1
package org.cardanofoundation.explorer.api.service.impl;
2
3
import java.util.ArrayList;
4
import java.util.Arrays;
5
import java.util.Comparator;
6
import java.util.Date;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.function.BinaryOperator;
10
import java.util.function.Function;
11
import java.util.stream.Collectors;
12
13
import lombok.RequiredArgsConstructor;
14
15
import org.springframework.data.domain.Page;
16
import org.springframework.data.domain.Pageable;
17
import org.springframework.data.util.Pair;
18
import org.springframework.stereotype.Service;
19
20
import org.cardanofoundation.explorer.api.common.enumeration.CommitteeStatus;
21
import org.cardanofoundation.explorer.api.exception.BusinessCode;
22
import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse;
23
import org.cardanofoundation.explorer.api.model.response.committee.CommitteeMemberResponse;
24
import org.cardanofoundation.explorer.api.model.response.committee.CommitteeOverviewResponse;
25
import org.cardanofoundation.explorer.api.model.response.drep.VotingProcedureChartResponse;
26
import org.cardanofoundation.explorer.api.projection.VotingProcedureProjection;
27
import org.cardanofoundation.explorer.api.repository.ledgersync.*;
28
import org.cardanofoundation.explorer.api.service.CCommitteeService;
29
import org.cardanofoundation.explorer.api.service.ProtocolParamService;
30
import org.cardanofoundation.explorer.common.entity.enumeration.CommitteeState;
31
import org.cardanofoundation.explorer.common.entity.enumeration.GovActionType;
32
import org.cardanofoundation.explorer.common.entity.enumeration.Vote;
33
import org.cardanofoundation.explorer.common.entity.ledgersync.CommitteeMember;
34
import org.cardanofoundation.explorer.common.entity.ledgersync.CommitteeRegistration;
35
import org.cardanofoundation.explorer.common.entity.ledgersync.EpochParam;
36
import org.cardanofoundation.explorer.common.exception.BusinessException;
37
38
@Service
39
@RequiredArgsConstructor
40
public class CCommitteeServiceImpl implements CCommitteeService {
41
42
  private final CommitteeMemberRepository committeeMemberRepository;
43
  private final GovernanceActionRepository governanceActionRepository;
44
  private final LatestVotingProcedureRepository latestVotingProcedureRepository;
45
  private final CommitteeRegistrationRepository committeeRegistrationRepository;
46
  private final EpochParamRepository epochParamRepository;
47
  private final EpochRepository epochRepository;
48
  private final VotingProcedureRepository votingProcedureRepository;
49
  private final CommitteeDeRegistrationRepository committeeDeRegistrationRepository;
50
  private final CommitteeRepository committeeRepository;
51
  private final ProtocolParamService protocolParamService;
52
53
  @Override
54
  public CommitteeOverviewResponse getCommitteeOverview() {
55
    EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam();
56
    long activeMembers =
57
        committeeMemberRepository.countActiveMembersByExpiredEpochGreaterThan(
58
            currentEpochParam.getEpochNo());
59
60
    CommitteeState committeeState =
61 2 1. getCommitteeOverview : negated conditional → NO_COVERAGE
2. getCommitteeOverview : changed conditional boundary → NO_COVERAGE
        activeMembers >= currentEpochParam.getCommitteeMinSize().intValue()
62
            ? CommitteeState.CONFIDENCE
63
            : CommitteeState.NO_CONFIDENCE;
64
65
    Double latestCCThreshold =
66
        committeeRepository
67
            .getLatestCCThreshold()
68
            .orElseGet(protocolParamService::getCCThresholdFromConwayGenesis);
69
70
    // TODO: get activeEpoch from lsv2 once implemented
71
    Integer activeEpoch =
72
        committeeMemberRepository.getMinExpireEpochOfActiveMembers(currentEpochParam.getEpochNo())
73 1 1. getCommitteeOverview : Replaced integer subtraction with addition → NO_COVERAGE
            - currentEpochParam.getCommitteeMaxTermLength().intValue();
74
75
    Long activeEpochSecondTime = epochRepository.getEpochSecondTimeByEpochNo(activeEpoch);
76
77
    List<GovActionType> govActionTypeList = new ArrayList<>(Arrays.asList(GovActionType.values()));
78
    govActionTypeList.removeAll(
79
        List.of(GovActionType.NO_CONFIDENCE, GovActionType.UPDATE_COMMITTEE));
80
81
    Long governanceVotes =
82
        governanceActionRepository.countGovThatAllowedToVoteByBlockTimeGreaterThanAndGovType(
83
            activeEpochSecondTime, govActionTypeList);
84
85
    // TODO: get from lsv2 once implemented
86
    String proposalPolicy = null;
87
88
    // TODO: get from lsv2 once implemented
89
    Long lastUpdate = activeEpochSecondTime;
90
91 1 1. getCommitteeOverview : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getCommitteeOverview → NO_COVERAGE
    return CommitteeOverviewResponse.builder()
92
        .currentState(committeeState)
93
        .proposalPolicy(proposalPolicy)
94
        .activeMembers(activeMembers)
95
        .threshold(latestCCThreshold)
96
        .governanceVotes(governanceVotes)
97 2 1. getCommitteeOverview : Replaced long multiplication with division → NO_COVERAGE
2. getCommitteeOverview : negated conditional → NO_COVERAGE
        .lastUpdate(lastUpdate == null ? null : new Date(lastUpdate * 1000))
98
        .build();
99
  }
100
101
  @Override
102
  public BaseFilterResponse<CommitteeMemberResponse> getCommitteeMembers(Pageable pageable) {
103
    EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam();
104
105
    Page<CommitteeMember> committeeMemberPages = committeeMemberRepository.findAll(pageable);
106
    List<String> coldKeys = committeeMemberPages.map(CommitteeMember::getHash).getContent();
107
108
    Map<String, String> hotKeyMap =
109
        committeeRegistrationRepository.getHotKeyOfCommitteeMemberByColdKeyIn(coldKeys).stream()
110
            .collect(
111
                Collectors.toMap(
112
                    CommitteeRegistration::getColdKey, CommitteeRegistration::getHotKey));
113
114
    Page<CommitteeMemberResponse> committeeMemberResponses =
115
        committeeMemberPages.map(
116
            committeeMember -> {
117
              CommitteeMemberResponse committeeMemberResponse = new CommitteeMemberResponse();
118 1 1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setScriptHash → NO_COVERAGE
              committeeMemberResponse.setScriptHash(committeeMember.getHash());
119 1 1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setPublicKey → NO_COVERAGE
              committeeMemberResponse.setPublicKey(hotKeyMap.get(committeeMember.getHash()));
120 1 1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setStatus → NO_COVERAGE
              committeeMemberResponse.setStatus(
121 2 1. lambda$getCommitteeMembers$0 : changed conditional boundary → NO_COVERAGE
2. lambda$getCommitteeMembers$0 : negated conditional → NO_COVERAGE
                  committeeMember.getExpiredEpoch() > currentEpochParam.getEpochNo()
122
                      ? CommitteeStatus.ACTIVE
123
                      : CommitteeStatus.EXPIRED);
124 1 1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setExpiredEpoch → NO_COVERAGE
              committeeMemberResponse.setExpiredEpoch(committeeMember.getExpiredEpoch());
125
              // TODO: get from lsv2 once implemented
126 1 1. lambda$getCommitteeMembers$0 : removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setActiveEpoch → NO_COVERAGE
              committeeMemberResponse.setActiveEpoch(
127
                  committeeMember.getExpiredEpoch()
128 1 1. lambda$getCommitteeMembers$0 : Replaced integer subtraction with addition → NO_COVERAGE
                      - currentEpochParam.getCommitteeMaxTermLength().intValue());
129 1 1. lambda$getCommitteeMembers$0 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getCommitteeMembers$0 → NO_COVERAGE
              return committeeMemberResponse;
130
            });
131
132 1 1. getCommitteeMembers : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getCommitteeMembers → NO_COVERAGE
    return new BaseFilterResponse<>(committeeMemberResponses);
133
  }
134
135
  @Override
136
  public CommitteeMemberResponse getCommitteeMemberDetail(String publicKey) {
137
    CommitteeRegistration committeeRegistration =
138
        committeeRegistrationRepository.getCommitteeRegistrationByHotKey(publicKey);
139
140 1 1. getCommitteeMemberDetail : negated conditional → NO_COVERAGE
    if (committeeRegistration == null) {
141
      throw new BusinessException(BusinessCode.COMMITTEE_MEMBER_NOT_FOUND);
142
    }
143
144
    CommitteeMember committeeMember =
145
        committeeMemberRepository
146
            .findById(committeeRegistration.getColdKey())
147 1 1. lambda$getCommitteeMemberDetail$1 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getCommitteeMemberDetail$1 → NO_COVERAGE
            .orElseThrow(() -> new BusinessException(BusinessCode.COMMITTEE_MEMBER_NOT_FOUND));
148
149
    EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam();
150
151
    // TODO: get activeEpoch from lsv2 once implemented
152
    Integer activeEpoch =
153
        committeeMemberRepository.getMinExpireEpochOfActiveMembers(currentEpochParam.getEpochNo())
154 1 1. getCommitteeMemberDetail : Replaced integer subtraction with addition → NO_COVERAGE
            - currentEpochParam.getCommitteeMaxTermLength().intValue();
155
    Long activeEpochSecondTime = epochRepository.getEpochSecondTimeByEpochNo(activeEpoch);
156
157
    Long resignedBlockTime =
158
        committeeDeRegistrationRepository.getResignationBlockTimeByColdKey(
159
            committeeMember.getHash());
160
161
    Long votedGovCount =
162
        latestVotingProcedureRepository.countVoteByVoterHash(
163
            committeeRegistration.getHotKey(), activeEpochSecondTime);
164
165
    List<GovActionType> govActionTypeList = new ArrayList<>(Arrays.asList(GovActionType.values()));
166
    govActionTypeList.removeAll(
167
        List.of(GovActionType.NO_CONFIDENCE, GovActionType.UPDATE_COMMITTEE));
168
169
    Long govAllowedToVote =
170
        governanceActionRepository.countGovThatAllowedToVoteByBlockTimeGreaterThanAndGovType(
171
            activeEpochSecondTime, govActionTypeList);
172
    Float votingParticipation =
173 2 1. getCommitteeMemberDetail : Replaced float division with multiplication → NO_COVERAGE
2. getCommitteeMemberDetail : negated conditional → NO_COVERAGE
        govAllowedToVote == 0 ? 0 : (float) votedGovCount / govAllowedToVote;
174
175 1 1. getCommitteeMemberDetail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getCommitteeMemberDetail → NO_COVERAGE
    return CommitteeMemberResponse.builder()
176
        .scriptHash(committeeRegistration.getColdKey())
177
        .publicKey(committeeRegistration.getHotKey())
178
        .status(
179 2 1. getCommitteeMemberDetail : negated conditional → NO_COVERAGE
2. getCommitteeMemberDetail : changed conditional boundary → NO_COVERAGE
            committeeMember.getExpiredEpoch() > currentEpochParam.getEpochNo()
180
                ? CommitteeStatus.ACTIVE
181
                : CommitteeStatus.EXPIRED)
182 1 1. getCommitteeMemberDetail : Replaced long multiplication with division → NO_COVERAGE
        .registeredAt(new Date(activeEpochSecondTime * 1000))
183 2 1. getCommitteeMemberDetail : negated conditional → NO_COVERAGE
2. getCommitteeMemberDetail : Replaced long multiplication with division → NO_COVERAGE
        .resignedAt(resignedBlockTime == null ? null : new Date(resignedBlockTime * 1000))
184
        .activeEpoch(activeEpoch)
185
        .expiredEpoch(committeeMember.getExpiredEpoch())
186
        .termDuration(currentEpochParam.getCommitteeMaxTermLength().intValue())
187
        .votingParticipation(votingParticipation)
188
        .build();
189
  }
190
191
  @Override
192
  public VotingProcedureChartResponse getVoteProcedureChart(
193
      String publicKey, GovActionType govActionType) {
194
    CommitteeRegistration committeeRegistration =
195
        committeeRegistrationRepository.getCommitteeRegistrationByHotKey(publicKey);
196
197 1 1. getVoteProcedureChart : negated conditional → NO_COVERAGE
    if (committeeRegistration == null) {
198
      throw new BusinessException(BusinessCode.COMMITTEE_MEMBER_NOT_FOUND);
199
    }
200
201
    EpochParam currentEpochParam = epochParamRepository.findCurrentEpochParam();
202
    // TODO: get activeEpoch from lsv2 once implemented
203
    Integer activeEpoch =
204
        committeeMemberRepository.getMinExpireEpochOfActiveMembers(currentEpochParam.getEpochNo())
205 1 1. getVoteProcedureChart : Replaced integer subtraction with addition → NO_COVERAGE
            - currentEpochParam.getCommitteeMaxTermLength().intValue();
206
    Long activeEpochSecondTime = epochRepository.getEpochSecondTimeByEpochNo(activeEpoch);
207
208
    List<VotingProcedureProjection> votingProcedureProjections =
209
        votingProcedureRepository.findVotingProcedureByVoterHashAndGovActionType(
210
            publicKey,
211 1 1. getVoteProcedureChart : negated conditional → NO_COVERAGE
            govActionType.equals(GovActionType.ALL) ? null : govActionType,
212
            activeEpochSecondTime);
213
    List<VotingProcedureProjection> votingProcedureProjectionListResponse =
214
        votingProcedureProjections.stream()
215
            .collect(
216
                Collectors.toMap(
217 1 1. lambda$getVoteProcedureChart$2 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getVoteProcedureChart$2 → NO_COVERAGE
                    e -> Pair.of(e.getGovActionTxHash(), e.getGovActionIndex()),
218
                    Function.identity(),
219
                    BinaryOperator.maxBy(
220
                        Comparator.comparing(VotingProcedureProjection::getBlockTime))))
221
            .values()
222
            .stream()
223
            .toList();
224
    Map<Vote, Long> counted =
225
        votingProcedureProjectionListResponse.stream()
226
            .collect(
227
                Collectors.groupingBy(VotingProcedureProjection::getVote, Collectors.counting()));
228
229 1 1. getVoteProcedureChart : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::getVoteProcedureChart → NO_COVERAGE
    return VotingProcedureChartResponse.builder()
230
        .dRepHash(publicKey)
231
        .govActionType(govActionType)
232
        .numberOfYesVote(counted.getOrDefault(Vote.YES, 0L))
233
        .numberOfNoVotes(counted.getOrDefault(Vote.NO, 0L))
234
        .numberOfAbstainVotes(counted.getOrDefault(Vote.ABSTAIN, 0L))
235
        .build();
236
  }
237
}

Mutations

61

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

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

73

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

91

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

97

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

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

118

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setScriptHash → NO_COVERAGE

119

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setPublicKey → NO_COVERAGE

120

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setStatus → NO_COVERAGE

121

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : lambda$getCommitteeMembers$0
Killed by : none
negated conditional → NO_COVERAGE

124

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setExpiredEpoch → NO_COVERAGE

126

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
removed call to org/cardanofoundation/explorer/api/model/response/committee/CommitteeMemberResponse::setActiveEpoch → NO_COVERAGE

128

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

129

1.1
Location : lambda$getCommitteeMembers$0
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getCommitteeMembers$0 → NO_COVERAGE

132

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

140

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

147

1.1
Location : lambda$getCommitteeMemberDetail$1
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getCommitteeMemberDetail$1 → NO_COVERAGE

154

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

173

1.1
Location : getCommitteeMemberDetail
Killed by : none
Replaced float division with multiplication → NO_COVERAGE

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

175

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

179

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

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

182

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

183

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

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

197

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

205

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

211

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

217

1.1
Location : lambda$getVoteProcedureChart$2
Killed by : none
replaced return value with null for org/cardanofoundation/explorer/api/service/impl/CCommitteeServiceImpl::lambda$getVoteProcedureChart$2 → NO_COVERAGE

229

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

Active mutators

Tests examined


Report generated by PIT 1.14.2