1 | package org.cardanofoundation.explorer.api.service.impl; | |
2 | ||
3 | import java.math.BigInteger; | |
4 | import java.nio.charset.StandardCharsets; | |
5 | import java.util.ArrayList; | |
6 | import java.util.HashMap; | |
7 | import java.util.LinkedHashMap; | |
8 | import java.util.List; | |
9 | import java.util.Map; | |
10 | import java.util.concurrent.CompletableFuture; | |
11 | import java.util.concurrent.TimeUnit; | |
12 | import java.util.function.Function; | |
13 | import java.util.stream.Collectors; | |
14 | ||
15 | import jakarta.annotation.PostConstruct; | |
16 | ||
17 | import lombok.RequiredArgsConstructor; | |
18 | import lombok.extern.log4j.Log4j2; | |
19 | ||
20 | import org.springframework.beans.factory.annotation.Value; | |
21 | import org.springframework.data.redis.core.RedisTemplate; | |
22 | import org.springframework.http.HttpStatusCode; | |
23 | import org.springframework.stereotype.Service; | |
24 | import org.springframework.util.CollectionUtils; | |
25 | import org.springframework.web.reactive.function.client.WebClient; | |
26 | ||
27 | import com.fasterxml.jackson.databind.JsonNode; | |
28 | import com.fasterxml.jackson.databind.ObjectMapper; | |
29 | import org.apache.commons.lang3.StringUtils; | |
30 | import reactor.core.publisher.Mono; | |
31 | ||
32 | import org.cardanofoundation.cf_product_tracing_aggregator.ProductAggregationRecord; | |
33 | import org.cardanofoundation.explorer.api.exception.BusinessCode; | |
34 | import org.cardanofoundation.explorer.api.mapper.ProductAggMapper; | |
35 | import org.cardanofoundation.explorer.api.model.metadatastandard.bolnisi.*; | |
36 | import org.cardanofoundation.explorer.api.model.response.BolnisiProjectNumberResponse; | |
37 | import org.cardanofoundation.explorer.api.repository.ledgersync.TxMetadataRepository; | |
38 | import org.cardanofoundation.explorer.api.service.BolnisiMetadataService; | |
39 | import org.cardanofoundation.explorer.api.util.CidUtils; | |
40 | import org.cardanofoundation.explorer.api.util.JwsUtils; | |
41 | import org.cardanofoundation.explorer.common.entity.ledgersync.TxMetadata; | |
42 | import org.cardanofoundation.explorer.common.exception.BusinessException; | |
43 | import org.cardanofoundation.explorer.common.utils.HexUtil; | |
44 | import org.cardanofoundation.explorer.common.utils.JsonUtil; | |
45 | ||
46 | @Service | |
47 | @RequiredArgsConstructor | |
48 | @Log4j2 | |
49 | public class BolnisiMetadataServiceImpl implements BolnisiMetadataService { | |
50 | ||
51 | private static final String BOLNISI_METADATA_KEY = "BOLNISI_METADATA:"; | |
52 | private final TxMetadataRepository txMetadataRepository; | |
53 | private final WebClient webClient; | |
54 | private final RedisTemplate<String, Object> redisTemplate; | |
55 | private final ProductAggMapper productAggMapper; | |
56 | ||
57 | @Value("${application.network}") | |
58 | private String network; | |
59 | ||
60 | @Value("${application.api.product-aggregator.latest-url}") | |
61 | private String latestProductAggregation; | |
62 | ||
63 | @Value("${application.api.bolnisi.off-chain}") | |
64 | private String offChainMetadataUrl; | |
65 | ||
66 | @Value("${application.api.bolnisi.public-key.fallback}") | |
67 | private String publicKeyFallbackUrl; | |
68 | ||
69 | @Value("${application.api.bolnisi.public-key.primary}") | |
70 | private String publicKeyPrimaryUrl; | |
71 | ||
72 | @Value("${application.api.bolnisi.public-key.conformity-cert}") | |
73 | private String publicKeyConformityCertUrl; | |
74 | ||
75 | @Override | |
76 | public MetadataBolnisi getBolnisiMetadata(String jsonMetadata) { | |
77 | // Processes JSON metadata to generate a MetadataBolnisi object | |
78 | MetadataBolnisi metadataBolnisi = getOnChainMetadata(jsonMetadata); | |
79 | ||
80 |
1
1. getBolnisiMetadata : negated conditional → KILLED |
if (!metadataBolnisi.isOnChainMetadataValid()) { |
81 |
1
1. getBolnisiMetadata : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getBolnisiMetadata → KILLED |
return metadataBolnisi; |
82 | } | |
83 | ||
84 |
1
1. getBolnisiMetadata : negated conditional → KILLED |
if (metadataBolnisi.getTag().equals("scm")) { |
85 | // retrieves off-chain metadata using getOffChainMetadata | |
86 | Map<String, List<Object>> offChainMetadata = | |
87 | getOffChainMetadataForWineryData(metadataBolnisi); | |
88 | ||
89 | // Verify the CID against the pretty-printed JSON of the off-chain metadata. | |
90 | boolean isCidVerified = | |
91 | CidUtils.verifyCid(metadataBolnisi.getCid(), JsonUtil.getPrettyJson(offChainMetadata)); | |
92 |
1
1. getBolnisiMetadata : negated conditional → KILLED |
if (!isCidVerified) { |
93 |
1
1. getBolnisiMetadata : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getBolnisiMetadata → KILLED |
return metadataBolnisi; |
94 | } | |
95 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCidVerified → KILLED |
metadataBolnisi.setCidVerified(true); |
96 | ||
97 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::verifyPublicKey → KILLED |
verifyPublicKey(metadataBolnisi); |
98 | ||
99 | Map<String, WineryData> wineryDataMap = | |
100 | metadataBolnisi.getWineryData().stream() | |
101 | .collect(Collectors.toMap(WineryData::getWineryId, Function.identity())); | |
102 | ||
103 | // For each piece of off-chain metadata, | |
104 | // it verifies the signature of each lot against the public key and updates the LotData | |
105 | // objects | |
106 | // accordingly. | |
107 |
1
1. getBolnisiMetadata : removed call to java/util/Map::forEach → KILLED |
offChainMetadata.forEach( |
108 | (key, value) -> { | |
109 | WineryData wineryData = wineryDataMap.get(key); | |
110 | ||
111 |
1
1. lambda$getBolnisiMetadata$0 : negated conditional → KILLED |
if (wineryData != null) { |
112 | List<LotData> lots = wineryData.getLots(); | |
113 |
2
1. lambda$getBolnisiMetadata$0 : negated conditional → KILLED 2. lambda$getBolnisiMetadata$0 : changed conditional boundary → KILLED |
for (int i = 0; i < lots.size(); i++) { |
114 | boolean isSignatureVerified = | |
115 |
1
1. lambda$getBolnisiMetadata$0 : negated conditional → KILLED |
wineryData.isPKeyVerified() |
116 |
1
1. lambda$getBolnisiMetadata$0 : negated conditional → KILLED |
&& JwsUtils.verifySignatureWithEd25519( |
117 | wineryData.getPublicKey(), | |
118 | lots.get(i).getSignature(), | |
119 | JsonUtil.getPrettyJson(value.get(i))); | |
120 | ||
121 | LotData lotData = lots.get(i); | |
122 |
1
1. lambda$getBolnisiMetadata$0 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/LotData::setOffChainData → SURVIVED |
lotData.setOffChainData(value.get(i)); |
123 |
1
1. lambda$getBolnisiMetadata$0 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/LotData::setSignatureVerified → KILLED |
lotData.setSignatureVerified(isSignatureVerified); |
124 | } | |
125 |
1
1. lambda$getBolnisiMetadata$0 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/WineryData::setLots → SURVIVED |
wineryData.setLots(lots); |
126 | wineryDataMap.put(key, wineryData); | |
127 | } | |
128 | }); | |
129 | ||
130 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setWineryData → SURVIVED |
metadataBolnisi.setWineryData(new ArrayList<>(wineryDataMap.values())); |
131 |
1
1. getBolnisiMetadata : negated conditional → NO_COVERAGE |
} else if (metadataBolnisi.getTag().equals("conformityCert") |
132 |
1
1. getBolnisiMetadata : negated conditional → NO_COVERAGE |
|| metadataBolnisi.getTag().equals("conformityCertRevoke")) { |
133 | // retrieves off-chain metadata | |
134 | Map<String, Object> offChainMetadata = getOffChainMetadataForCertData(metadataBolnisi); | |
135 | ||
136 | // Extract certificate data list and certificate numbers | |
137 | List<Object> certDataList = new ArrayList<>(offChainMetadata.values()); | |
138 | List<String> certNumbers = new ArrayList<>(offChainMetadata.keySet()); | |
139 | ||
140 | // Verify the CID against the pretty-printed JSON of the off-chain metadata. | |
141 | boolean isCidVerified = | |
142 | CidUtils.verifyCid(metadataBolnisi.getCid(), JsonUtil.getPrettyJson(certDataList)); | |
143 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCidVerified → NO_COVERAGE |
metadataBolnisi.setCidVerified(isCidVerified); |
144 |
1
1. getBolnisiMetadata : negated conditional → NO_COVERAGE |
if (!isCidVerified) { |
145 |
1
1. getBolnisiMetadata : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getBolnisiMetadata → NO_COVERAGE |
return metadataBolnisi; |
146 | } | |
147 | ||
148 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::verifyPKeyConformityCert → NO_COVERAGE |
verifyPKeyConformityCert(metadataBolnisi); |
149 | ||
150 | // Map off-chain metadata to CertData and mark signature as verified | |
151 | CertData certData = metadataBolnisi.getCertData(); | |
152 | List<CertDetailsData> certs = certData.getCerts(); | |
153 |
2
1. getBolnisiMetadata : changed conditional boundary → NO_COVERAGE 2. getBolnisiMetadata : negated conditional → NO_COVERAGE |
for (int i = 0; i < certs.size(); i++) { |
154 | String certNo = certNumbers.get(i); | |
155 | CertDetailsData cert = certs.get(i); | |
156 | ||
157 | boolean isSignatureVerified = | |
158 |
1
1. getBolnisiMetadata : negated conditional → NO_COVERAGE |
certData.isPKeyVerified() |
159 |
1
1. getBolnisiMetadata : negated conditional → NO_COVERAGE |
&& JwsUtils.verifySignatureWithEd25519( |
160 | certData.getPublicKey(), | |
161 | cert.getSignature(), | |
162 | JsonUtil.getPrettyJson(offChainMetadata.get(certNo))); | |
163 | ||
164 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertDetailsData::setCertNo → NO_COVERAGE |
cert.setCertNo(certNo); |
165 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertDetailsData::setOffChainData → NO_COVERAGE |
cert.setOffChainData(offChainMetadata.get(certNo)); |
166 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertDetailsData::setSignatureVerified → NO_COVERAGE |
cert.setSignatureVerified(isSignatureVerified); |
167 | } | |
168 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertData::setCerts → NO_COVERAGE |
certData.setCerts(certs); |
169 |
1
1. getBolnisiMetadata : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCertData → NO_COVERAGE |
metadataBolnisi.setCertData(certData); |
170 | } | |
171 |
1
1. getBolnisiMetadata : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getBolnisiMetadata → KILLED |
return metadataBolnisi; |
172 | } | |
173 | ||
174 | @Override | |
175 | public WineryData getWineryData(String txHash, String wineryId) { | |
176 | List<TxMetadata> txMetadataList = | |
177 | txMetadataRepository.findAllByTxHash(txHash).stream() | |
178 |
2
1. lambda$getWineryData$1 : replaced boolean return with true for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getWineryData$1 → SURVIVED 2. lambda$getWineryData$1 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getWineryData$1 → KILLED |
.filter(txMetadata -> txMetadata.getKey().equals(BigInteger.valueOf(1904))) |
179 | .collect(Collectors.toList()); | |
180 | ||
181 |
1
1. getWineryData : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getWineryData → KILLED |
return txMetadataList.stream() |
182 |
1
1. lambda$getWineryData$2 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getWineryData$2 → KILLED |
.map(txMetadata -> getBolnisiMetadata(txMetadata.getJson())) |
183 | .map(MetadataBolnisi::getWineryData) | |
184 | .flatMap(List::stream) | |
185 |
2
1. lambda$getWineryData$3 : replaced boolean return with true for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getWineryData$3 → SURVIVED 2. lambda$getWineryData$3 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getWineryData$3 → KILLED |
.filter(wineryData -> wineryData.getWineryId().equals(wineryId)) |
186 | .findFirst() | |
187 | .orElse(null); | |
188 | } | |
189 | ||
190 | @Override | |
191 | public CertDetailsData getCertDetailsData(String txHash, String certNo) { | |
192 | List<TxMetadata> txMetadataList = | |
193 | txMetadataRepository.findAllByTxHash(txHash).stream() | |
194 |
2
1. lambda$getCertDetailsData$4 : replaced boolean return with true for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getCertDetailsData$4 → NO_COVERAGE 2. lambda$getCertDetailsData$4 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getCertDetailsData$4 → NO_COVERAGE |
.filter(txMetadata -> txMetadata.getKey().equals(BigInteger.valueOf(1904))) |
195 | .toList(); | |
196 | ||
197 |
1
1. getCertDetailsData : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getCertDetailsData → NO_COVERAGE |
return txMetadataList.stream() |
198 |
1
1. lambda$getCertDetailsData$5 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getCertDetailsData$5 → NO_COVERAGE |
.map(txMetadata -> getBolnisiMetadata(txMetadata.getJson())) |
199 |
1
1. lambda$getCertDetailsData$6 : replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getCertDetailsData$6 → NO_COVERAGE |
.map(metadataBolnisi -> metadataBolnisi.getCertData().getCerts()) |
200 | .flatMap(List::stream) | |
201 |
2
1. lambda$getCertDetailsData$7 : replaced boolean return with true for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getCertDetailsData$7 → NO_COVERAGE 2. lambda$getCertDetailsData$7 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getCertDetailsData$7 → NO_COVERAGE |
.filter(certData -> certData.getCertNo().equals(certNo)) |
202 | .findFirst() | |
203 | .orElse(null); | |
204 | } | |
205 | ||
206 | @Override | |
207 | public BolnisiProjectNumberResponse getBolnisiProjectNumber() { | |
208 |
1
1. getBolnisiProjectNumber : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getBolnisiProjectNumber → NO_COVERAGE |
return webClient |
209 | .get() | |
210 | .uri(latestProductAggregation) | |
211 | .retrieve() | |
212 | .bodyToMono(ProductAggregationRecord.class) | |
213 | .map(productAggMapper::toBolnisiProjectResponse) | |
214 | .block(); | |
215 | } | |
216 | ||
217 | /** | |
218 | * Verifies the public keys associated with each winery in the provided MetadataBolnisi object. | |
219 | * The method retrieves cached public keys from Redis and compares them with the public keys | |
220 | * on-chain. If a public key is not found in the cache, it is fetched from an external API using | |
221 | * WebClient. Any errors encountered during the API call are logged, and the availability flags on | |
222 | * the MetadataBolnisi and WineryData objects are updated accordingly. The verified public keys | |
223 | * are then stored back in Redis with an expiration time of 1 day. Finally, the verification | |
224 | * status of each winery's public key is updated within the MetadataBolnisi object. | |
225 | * | |
226 | * @param metadataBolnisi The MetadataBolnisi object containing the winery data to be verified. | |
227 | */ | |
228 | private void verifyPublicKey(MetadataBolnisi metadataBolnisi) { | |
229 | String publicKeyRedisKey = getRedisKey(BOLNISI_METADATA_KEY + publicKeyPrimaryUrl); | |
230 | String publicKeyFallbackRedisKey = getRedisKey(BOLNISI_METADATA_KEY + publicKeyFallbackUrl); | |
231 | Map<String, String> pKeyRedisCachedMap = new HashMap<>(); | |
232 | List<CompletableFuture<Map<String, String>>> completableFutures = new ArrayList<>(); | |
233 | ||
234 | metadataBolnisi | |
235 | .getWineryData() | |
236 |
1
1. verifyPublicKey : removed call to java/util/List::forEach → KILLED |
.forEach( |
237 | wineryData -> { | |
238 | String pKeyCached = | |
239 | (String) | |
240 | redisTemplate.opsForHash().get(publicKeyRedisKey, wineryData.getWineryId()); | |
241 | String pKeyFallbackCached = | |
242 | (String) | |
243 | redisTemplate | |
244 | .opsForHash() | |
245 | .get(publicKeyFallbackRedisKey, wineryData.getWineryId()); | |
246 |
1
1. lambda$verifyPublicKey$12 : negated conditional → KILLED |
if (pKeyCached != null) { |
247 | pKeyRedisCachedMap.put(wineryData.getWineryId(), pKeyCached); | |
248 |
1
1. lambda$verifyPublicKey$12 : negated conditional → KILLED |
} else if (pKeyFallbackCached != null) { |
249 | pKeyRedisCachedMap.put(wineryData.getWineryId(), pKeyFallbackCached); | |
250 | } else { | |
251 | completableFutures.add( | |
252 | callWebclient(publicKeyPrimaryUrl, byte[].class, wineryData.getWineryId()) | |
253 | .map( | |
254 | bytes -> { | |
255 | String pKey = HexUtil.encodeHexString(bytes); | |
256 | redisTemplate | |
257 | .opsForHash() | |
258 | .putIfAbsent(publicKeyRedisKey, wineryData.getWineryId(), pKey); | |
259 | redisTemplate.expire(publicKeyRedisKey, 1, TimeUnit.DAYS); | |
260 |
1
1. lambda$verifyPublicKey$8 : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$8 → KILLED |
return Map.of(wineryData.getWineryId(), pKey); |
261 | }) | |
262 | .onErrorResume( | |
263 | ex -> { | |
264 | log.warn("Primary URL failed, attempting fallback URL", ex); | |
265 |
1
1. lambda$verifyPublicKey$10 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$10 → NO_COVERAGE |
return callWebclient( |
266 | publicKeyFallbackUrl, byte[].class, wineryData.getWineryId()) | |
267 | .map( | |
268 | fallbackBytes -> { | |
269 | String pKey = HexUtil.encodeHexString(fallbackBytes); | |
270 | redisTemplate | |
271 | .opsForHash() | |
272 | .putIfAbsent( | |
273 | publicKeyFallbackRedisKey, | |
274 | wineryData.getWineryId(), | |
275 | pKey); | |
276 | redisTemplate.expire( | |
277 | publicKeyFallbackRedisKey, 1, TimeUnit.DAYS); | |
278 |
1
1. lambda$verifyPublicKey$9 : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$9 → NO_COVERAGE |
return Map.of(wineryData.getWineryId(), pKey); |
279 | }); | |
280 | }) | |
281 | .toFuture() | |
282 | .exceptionally( | |
283 | ex -> { | |
284 | log.error("Error while getting public key from external API", ex); | |
285 |
1
1. lambda$verifyPublicKey$11 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/WineryData::setPKeyVerified → NO_COVERAGE |
wineryData.setPKeyVerified(false); |
286 |
1
1. lambda$verifyPublicKey$11 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/WineryData::setExternalApiAvailable → NO_COVERAGE |
wineryData.setExternalApiAvailable(false); |
287 |
1
1. lambda$verifyPublicKey$11 : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$11 → NO_COVERAGE |
return null; |
288 | })); | |
289 | } | |
290 | }); | |
291 | ||
292 | Map<String, String> wineryPkeyMap = | |
293 | completableFutures.stream() | |
294 | .map(CompletableFuture::join) | |
295 |
2
1. lambda$verifyPublicKey$13 : replaced boolean return with true for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$13 → SURVIVED 2. lambda$verifyPublicKey$13 : negated conditional → KILLED |
.filter(map -> !CollectionUtils.isEmpty(map)) |
296 |
1
1. lambda$verifyPublicKey$14 : replaced return value with Stream.empty for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$14 → KILLED |
.flatMap(map -> map.entrySet().stream()) |
297 |
1
1. lambda$verifyPublicKey$15 : replaced return value with "" for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPublicKey$15 → NO_COVERAGE |
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a)); |
298 | ||
299 |
1
1. verifyPublicKey : removed call to java/util/Map::putAll → SURVIVED |
wineryPkeyMap.putAll(pKeyRedisCachedMap); |
300 | ||
301 | metadataBolnisi | |
302 | .getWineryData() | |
303 |
1
1. verifyPublicKey : removed call to java/util/List::forEach → KILLED |
.forEach( |
304 | wineryData -> { | |
305 | String pKeyOnChain = wineryPkeyMap.get(wineryData.getWineryId()); | |
306 |
1
1. lambda$verifyPublicKey$16 : negated conditional → KILLED |
boolean isPKeyVerified = |
307 | pKeyOnChain != null | |
308 | && removePrefixHexString(wineryData.getPublicKey()) | |
309 |
1
1. lambda$verifyPublicKey$16 : negated conditional → KILLED |
.equals(removePrefixHexString(pKeyOnChain)); |
310 |
1
1. lambda$verifyPublicKey$16 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/WineryData::setPKeyVerified → KILLED |
wineryData.setPKeyVerified(isPKeyVerified); |
311 | }); | |
312 | } | |
313 | ||
314 | private void verifyPKeyConformityCert(MetadataBolnisi metadataBolnisi) { | |
315 | CertData certData = metadataBolnisi.getCertData(); | |
316 | ||
317 | String publicKeyRedisKey = getRedisKey(BOLNISI_METADATA_KEY + publicKeyConformityCertUrl); | |
318 | String pKeyCached = | |
319 | (String) redisTemplate.opsForHash().get(publicKeyRedisKey, metadataBolnisi.getCid()); | |
320 | ||
321 | String pKeyOnChain = | |
322 |
1
1. verifyPKeyConformityCert : negated conditional → NO_COVERAGE |
pKeyCached != null |
323 | ? pKeyCached | |
324 | : callWebclient(publicKeyConformityCertUrl, byte[].class) | |
325 | .map(HexUtil::encodeHexString) | |
326 | .onErrorResume( | |
327 | ex -> { | |
328 | log.error("Error while getting public key from external API", ex); | |
329 |
1
1. lambda$verifyPKeyConformityCert$17 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertData::setPKeyVerified → NO_COVERAGE |
certData.setPKeyVerified(false); |
330 |
1
1. lambda$verifyPKeyConformityCert$17 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertData::setExternalApiAvailable → NO_COVERAGE |
certData.setExternalApiAvailable(false); |
331 |
1
1. lambda$verifyPKeyConformityCert$17 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$verifyPKeyConformityCert$17 → NO_COVERAGE |
return Mono.empty(); |
332 | }) | |
333 | .block(); | |
334 | ||
335 |
1
1. verifyPKeyConformityCert : negated conditional → NO_COVERAGE |
if (pKeyOnChain != null) { |
336 | redisTemplate | |
337 | .opsForHash() | |
338 | .putIfAbsent(publicKeyRedisKey, metadataBolnisi.getCid(), pKeyOnChain); | |
339 | redisTemplate.expire(publicKeyRedisKey, 1, TimeUnit.DAYS); | |
340 | } | |
341 | ||
342 |
2
1. verifyPKeyConformityCert : negated conditional → NO_COVERAGE 2. verifyPKeyConformityCert : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/CertData::setPKeyVerified → NO_COVERAGE |
certData.setPKeyVerified( |
343 | pKeyOnChain != null | |
344 | && removePrefixHexString(certData.getPublicKey()) | |
345 |
1
1. verifyPKeyConformityCert : negated conditional → NO_COVERAGE |
.equals(removePrefixHexString(pKeyOnChain))); |
346 | } | |
347 | ||
348 | /** | |
349 | * Parses JSON metadata and constructs a MetadataBolnisi object based on the parsed data. This | |
350 | * method assumes that the input JSON contains a field named "st" which indicates the type of | |
351 | * metadata. If the "st" field has the value "georgianWine", the method proceeds to extract | |
352 | * additional fields such as "cid" and "d". The "d" field is expected to contain winery data, | |
353 | * which is processed to create a list of WineryData objects. Each WineryData object includes a | |
354 | * list of LotData objects, which are constructed from the signatures present in the JSON. If any | |
355 | * exceptions occur during parsing or processing, the method logs the error and sets the | |
356 | * appropriate flags on the MetadataBolnisi builder. | |
357 | * | |
358 | * @param jsonMetadata The JSON string containing the on-chain metadata. | |
359 | * @return A MetadataBolnisi object populated with the parsed data. If an exception occurs, the | |
360 | * object will have its verification flags set to false. | |
361 | * @throws Exception If there is an issue with parsing the JSON or processing the extracted data. | |
362 | */ | |
363 | private MetadataBolnisi getOnChainMetadata(String jsonMetadata) { | |
364 | MetadataBolnisi.MetadataBolnisiBuilder metadataBolnisiBuilder = MetadataBolnisi.builder(); | |
365 | metadataBolnisiBuilder.isExternalApiAvailable(true); | |
366 | metadataBolnisiBuilder.isOnChainMetadataValid(true); | |
367 | try { | |
368 | ObjectMapper objectMapper = new ObjectMapper(); | |
369 | JsonNode metadataNode = objectMapper.readTree(jsonMetadata); | |
370 | // get value with key "cid" | |
371 | String cid = metadataNode.get("cid").asText(); | |
372 | metadataBolnisiBuilder.cid(cid); | |
373 | String st = metadataNode.get("st").asText(); | |
374 | String t = metadataNode.get("t").asText(); | |
375 | metadataBolnisiBuilder.tag(t); | |
376 |
1
1. getOnChainMetadata : negated conditional → KILLED |
if (st.equals("georgianWine")) { |
377 |
2
1. getOnChainMetadata : negated conditional → KILLED 2. getOnChainMetadata : negated conditional → KILLED |
if (t.equals("conformityCert") || t.equals("conformityCertRevoke")) { |
378 | List<CertDetailsData> certDetailsDataList = new ArrayList<>(); | |
379 |
1
1. getOnChainMetadata : negated conditional → NO_COVERAGE |
if (metadataNode.get("s").isArray()) { |
380 | metadataNode | |
381 | .get("s") | |
382 |
1
1. getOnChainMetadata : removed call to com/fasterxml/jackson/databind/JsonNode::forEach → NO_COVERAGE |
.forEach( |
383 | signature -> { | |
384 | CertDetailsData certs = | |
385 | CertDetailsData.builder() | |
386 | .signature(removePrefixHexString(signature.asText())) | |
387 | .build(); | |
388 | certDetailsDataList.add(certs); | |
389 | }); | |
390 | } | |
391 | ||
392 | metadataBolnisiBuilder.certData( | |
393 | CertData.builder() | |
394 | .certs(certDetailsDataList) | |
395 | .isExternalApiAvailable(true) | |
396 | .publicKey(removePrefixHexString(metadataNode.get("pk").asText())) | |
397 | .header(removePrefixHexString(metadataNode.get("h").asText())) | |
398 | .build()); | |
399 |
1
1. getOnChainMetadata : negated conditional → KILLED |
} else if (t.equals("scm")) { |
400 | List<WineryData> wineryDataList = new ArrayList<>(); | |
401 | // for each wineryId in the metadataNode of key "d" | |
402 | metadataNode | |
403 | .get("d") | |
404 | .fieldNames() | |
405 |
1
1. getOnChainMetadata : removed call to java/util/Iterator::forEachRemaining → KILLED |
.forEachRemaining( |
406 | wineryId -> { | |
407 | // get wineryNode from the metadataNode of key "d" with wineryId | |
408 | JsonNode wineryNode = metadataNode.get("d").get(wineryId); | |
409 | List<LotData> lots = new ArrayList<>(); | |
410 | ||
411 | // get signature from the wineryNode of key "s" | |
412 |
1
1. lambda$getOnChainMetadata$20 : negated conditional → KILLED |
if (wineryNode.get("s").isArray()) { |
413 | // put all signatures into lots | |
414 | wineryNode | |
415 | .get("s") | |
416 |
1
1. lambda$getOnChainMetadata$20 : removed call to com/fasterxml/jackson/databind/JsonNode::forEach → KILLED |
.forEach( |
417 | signature -> { | |
418 | LotData lotData = | |
419 | LotData.builder() | |
420 | .signature(removePrefixHexString(signature.asText())) | |
421 | .build(); | |
422 | lots.add(lotData); | |
423 | }); | |
424 | } | |
425 | ||
426 | WineryData wineryData = | |
427 | WineryData.builder() | |
428 | .wineryId(wineryId) | |
429 | .isExternalApiAvailable(true) | |
430 | .publicKey(removePrefixHexString(wineryNode.get("pk").asText())) | |
431 | .header(removePrefixHexString(wineryNode.get("h").asText())) | |
432 | .lots(lots) | |
433 | .build(); | |
434 | wineryDataList.add(wineryData); | |
435 | }); | |
436 | metadataBolnisiBuilder.wineryData(wineryDataList); | |
437 | } else { | |
438 | metadataBolnisiBuilder.isOnChainMetadataValid(false); | |
439 | } | |
440 | } else { | |
441 | metadataBolnisiBuilder.isOnChainMetadataValid(false); | |
442 | } | |
443 | ||
444 | } catch (Exception e) { | |
445 | metadataBolnisiBuilder.isCidVerified(false); | |
446 | metadataBolnisiBuilder.isOnChainMetadataValid(false); | |
447 | log.error("Error while getting data from json", e); | |
448 | } | |
449 |
1
1. getOnChainMetadata : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOnChainMetadata → KILLED |
return metadataBolnisiBuilder.build(); |
450 | } | |
451 | ||
452 | /** | |
453 | * Retrieves off-chain metadata associated with a given MetadataBolnisi object. The method first | |
454 | * checks if the CID (Content Identifier) of the MetadataBolnisi object is empty. If it is not | |
455 | * empty, it attempts to retrieve the metadata from Redis using the CID as the key. If the | |
456 | * metadata is found in Redis, it is returned immediately. Otherwise, the method makes a call to | |
457 | * an external API to fetch the metadata. The fetched metadata is then stored in Redis for future | |
458 | * use and set to expire after 1 day. If any errors occur during the process, they are logged, and | |
459 | * the MetadataBolnisi object is updated accordingly. | |
460 | * | |
461 | * @param metadataBolnisi The MetadataBolnisi object containing the CID and other related data. | |
462 | * @return A map where the keys are strings and the values are lists of objects representing the | |
463 | * off-chain metadata. Returns null if the CID is empty or if no metadata could be retrieved. | |
464 | */ | |
465 | @SuppressWarnings("unchecked") | |
466 | public Map<String, List<Object>> getOffChainMetadataForWineryData( | |
467 | MetadataBolnisi metadataBolnisi) { | |
468 |
1
1. getOffChainMetadataForWineryData : negated conditional → KILLED |
if (StringUtils.isEmpty(metadataBolnisi.getCid())) { |
469 |
1
1. getOffChainMetadataForWineryData : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOffChainMetadataForWineryData → SURVIVED |
return null; |
470 | } | |
471 | ||
472 | String offChainRedisKey = getRedisKey(BOLNISI_METADATA_KEY + offChainMetadataUrl); | |
473 | Object metadataRedisCached = | |
474 | redisTemplate.opsForHash().get(offChainRedisKey, metadataBolnisi.getCid()); | |
475 | ||
476 |
1
1. getOffChainMetadataForWineryData : negated conditional → KILLED |
if (metadataRedisCached != null) { |
477 |
1
1. getOffChainMetadataForWineryData : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOffChainMetadataForWineryData → KILLED |
return (Map<String, List<Object>>) metadataRedisCached; |
478 | } | |
479 | ||
480 | Map<String, List<Object>> offChainMetadata = | |
481 | callWebclient(offChainMetadataUrl, String.class, metadataBolnisi.getCid()) | |
482 | .flatMap( | |
483 | actualOffChainURL -> | |
484 |
1
1. lambda$getOffChainMetadataForWineryData$21 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getOffChainMetadataForWineryData$21 → SURVIVED |
callWebclient(actualOffChainURL.replace("%2F", "/"), LinkedHashMap.class)) |
485 | .doOnSuccess( | |
486 | linkedHashMap -> { | |
487 |
1
1. lambda$getOffChainMetadataForWineryData$22 : negated conditional → NO_COVERAGE |
if (CollectionUtils.isEmpty(linkedHashMap)) { |
488 |
1
1. lambda$getOffChainMetadataForWineryData$22 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCidVerified → NO_COVERAGE |
metadataBolnisi.setCidVerified(false); |
489 |
1
1. lambda$getOffChainMetadataForWineryData$22 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setWineryData → NO_COVERAGE |
metadataBolnisi.setWineryData(null); |
490 | } | |
491 | }) | |
492 | .onErrorComplete( | |
493 | throwable -> { | |
494 | log.error("Error while getting bolnisi off-chain metadata", throwable); | |
495 |
1
1. lambda$getOffChainMetadataForWineryData$23 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setExternalApiAvailable → KILLED |
metadataBolnisi.setExternalApiAvailable(false); |
496 |
1
1. lambda$getOffChainMetadataForWineryData$23 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCidVerified → SURVIVED |
metadataBolnisi.setCidVerified(false); |
497 |
1
1. lambda$getOffChainMetadataForWineryData$23 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setWineryData → KILLED |
metadataBolnisi.setWineryData(null); |
498 |
1
1. lambda$getOffChainMetadataForWineryData$23 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getOffChainMetadataForWineryData$23 → KILLED |
return true; |
499 | }) | |
500 | .block(); | |
501 | ||
502 |
1
1. getOffChainMetadataForWineryData : negated conditional → SURVIVED |
if (offChainMetadata != null) { |
503 |
1
1. getOffChainMetadataForWineryData : removed call to org/springframework/data/redis/core/HashOperations::put → NO_COVERAGE |
redisTemplate.opsForHash().put(offChainRedisKey, metadataBolnisi.getCid(), offChainMetadata); |
504 | redisTemplate.expire(offChainRedisKey, 1, TimeUnit.DAYS); | |
505 | } | |
506 | ||
507 |
1
1. getOffChainMetadataForWineryData : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOffChainMetadataForWineryData → SURVIVED |
return offChainMetadata; |
508 | } | |
509 | ||
510 | @SuppressWarnings("unchecked") | |
511 | private Map<String, Object> getOffChainMetadataForCertData(MetadataBolnisi metadataBolnisi) { | |
512 | // Ensure the CID is present before proceeding | |
513 |
1
1. getOffChainMetadataForCertData : negated conditional → NO_COVERAGE |
if (StringUtils.isEmpty(metadataBolnisi.getCid())) { |
514 |
1
1. getOffChainMetadataForCertData : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOffChainMetadataForCertData → NO_COVERAGE |
return null; |
515 | } | |
516 | ||
517 | // Try to fetch from Redis first | |
518 | String offChainRedisKey = getRedisKey(BOLNISI_METADATA_KEY + offChainMetadataUrl); | |
519 | Object metadataRedisCached = | |
520 | redisTemplate.opsForHash().get(offChainRedisKey, metadataBolnisi.getCid()); | |
521 | ||
522 |
1
1. getOffChainMetadataForCertData : negated conditional → NO_COVERAGE |
if (metadataRedisCached != null) { |
523 |
1
1. getOffChainMetadataForCertData : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOffChainMetadataForCertData → NO_COVERAGE |
return (Map<String, Object>) metadataRedisCached; |
524 | } | |
525 | ||
526 | // Fetch from the external API if Redis cache is empty | |
527 | List<LinkedHashMap<String, Object>> offChainMetadataList = | |
528 | callWebclient(offChainMetadataUrl, String.class, metadataBolnisi.getCid()) | |
529 | .flatMap( | |
530 | actualOffChainURL -> | |
531 |
1
1. lambda$getOffChainMetadataForCertData$24 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getOffChainMetadataForCertData$24 → NO_COVERAGE |
callWebclient(actualOffChainURL.replace("%2F", "/"), List.class)) |
532 | .doOnSuccess( | |
533 | linkedHashMap -> { | |
534 |
1
1. lambda$getOffChainMetadataForCertData$25 : negated conditional → NO_COVERAGE |
if (CollectionUtils.isEmpty(linkedHashMap)) { |
535 |
1
1. lambda$getOffChainMetadataForCertData$25 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCidVerified → NO_COVERAGE |
metadataBolnisi.setCidVerified(false); |
536 |
1
1. lambda$getOffChainMetadataForCertData$25 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setWineryData → NO_COVERAGE |
metadataBolnisi.setWineryData(null); |
537 | } | |
538 | }) | |
539 | .onErrorComplete( | |
540 | throwable -> { | |
541 | log.error("Error while getting bolnisi off-chain metadata", throwable); | |
542 |
1
1. lambda$getOffChainMetadataForCertData$26 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setExternalApiAvailable → NO_COVERAGE |
metadataBolnisi.setExternalApiAvailable(false); |
543 |
1
1. lambda$getOffChainMetadataForCertData$26 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setCidVerified → NO_COVERAGE |
metadataBolnisi.setCidVerified(false); |
544 |
1
1. lambda$getOffChainMetadataForCertData$26 : removed call to org/cardanofoundation/explorer/api/model/metadatastandard/bolnisi/MetadataBolnisi::setWineryData → NO_COVERAGE |
metadataBolnisi.setWineryData(null); |
545 |
1
1. lambda$getOffChainMetadataForCertData$26 : replaced boolean return with false for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$getOffChainMetadataForCertData$26 → NO_COVERAGE |
return true; |
546 | }) | |
547 | .block(); | |
548 | ||
549 | Map<String, Object> offChainMetadataMap = new HashMap<>(); | |
550 |
1
1. getOffChainMetadataForCertData : negated conditional → NO_COVERAGE |
if (offChainMetadataList != null) { |
551 | // Populate the map with certificate_number as key and the json object as value | |
552 | for (LinkedHashMap<String, Object> certificate : offChainMetadataList) { | |
553 | String certificateNumber = (String) certificate.get("certificate_number"); | |
554 |
1
1. getOffChainMetadataForCertData : negated conditional → NO_COVERAGE |
if (certificateNumber != null) { |
555 | offChainMetadataMap.put(certificateNumber, certificate); | |
556 | } | |
557 | } | |
558 | ||
559 | redisTemplate | |
560 | .opsForHash() | |
561 |
1
1. getOffChainMetadataForCertData : removed call to org/springframework/data/redis/core/HashOperations::put → NO_COVERAGE |
.put(offChainRedisKey, metadataBolnisi.getCid(), offChainMetadataMap); |
562 | redisTemplate.expire(offChainRedisKey, 1, TimeUnit.DAYS); | |
563 | } | |
564 | ||
565 |
1
1. getOffChainMetadataForCertData : replaced return value with Collections.emptyMap for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getOffChainMetadataForCertData → NO_COVERAGE |
return offChainMetadataMap; |
566 | } | |
567 | ||
568 | /** | |
569 | * Executes a GET request using WebClient to retrieve data from a specified URL. The response body | |
570 | * is deserialized into an instance of the provided class type. This method handles HTTP status | |
571 | * codes and performs custom actions based on them: - For server errors (5xx), it checks if the | |
572 | * response body contains the string "703". If it does not, a BusinessException with code | |
573 | * EXTERNAL_API_IS_NOT_AVAILABLE is thrown. - For client errors (4xx), it simply returns an empty | |
574 | * Mono without throwing an exception. | |
575 | * | |
576 | * @param <T> The type of object to which the response body should be converted. | |
577 | * @param url The URL to send the GET request to. | |
578 | * @param clazz The class type to which the response body should be converted. | |
579 | * @param vars Optional URI variables to replace placeholders in the URL template. | |
580 | * @return A Mono containing the deserialized response body of the specified type T. | |
581 | * @throws BusinessException If a server error occurs and the response body does not contain | |
582 | * "703". | |
583 | */ | |
584 | private <T> Mono<T> callWebclient(String url, Class<T> clazz, Object... vars) { | |
585 |
1
1. callWebclient : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::callWebclient → KILLED |
return webClient |
586 | .get() | |
587 | .uri(url, vars) | |
588 | .acceptCharset(StandardCharsets.UTF_8) | |
589 | .retrieve() | |
590 | .onStatus( | |
591 | HttpStatusCode::is5xxServerError, | |
592 | clientResponse -> | |
593 |
1
1. lambda$callWebclient$28 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$callWebclient$28 → NO_COVERAGE |
clientResponse |
594 | .bodyToMono(String.class) | |
595 | .flatMap( | |
596 | s -> { | |
597 |
3
1. lambda$callWebclient$27 : negated conditional → NO_COVERAGE 2. lambda$callWebclient$27 : negated conditional → NO_COVERAGE 3. lambda$callWebclient$27 : negated conditional → NO_COVERAGE |
if (s == null || s.isEmpty() || !s.contains("703")) { |
598 |
1
1. lambda$callWebclient$27 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$callWebclient$27 → NO_COVERAGE |
return Mono.error( |
599 | new BusinessException(BusinessCode.EXTERNAL_API_IS_NOT_AVAILABLE)); | |
600 | } else { | |
601 |
1
1. lambda$callWebclient$27 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$callWebclient$27 → NO_COVERAGE |
return Mono.empty(); |
602 | } | |
603 | })) | |
604 |
1
1. lambda$callWebclient$29 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::lambda$callWebclient$29 → NO_COVERAGE |
.onStatus(HttpStatusCode::is4xxClientError, clientResponse -> Mono.empty()) |
605 | .bodyToMono(clazz); | |
606 | } | |
607 | ||
608 | private String removePrefixHexString(String hexString) { | |
609 |
2
1. removePrefixHexString : replaced return value with "" for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::removePrefixHexString → KILLED 2. removePrefixHexString : negated conditional → KILLED |
return hexString.startsWith("0x") ? hexString.substring(2) : hexString; |
610 | } | |
611 | ||
612 | private String getRedisKey(String value) { | |
613 |
1
1. getRedisKey : replaced return value with "" for org/cardanofoundation/explorer/api/service/impl/BolnisiMetadataServiceImpl::getRedisKey → KILLED |
return String.format("%s_%s", network, value).toUpperCase(); |
614 | } | |
615 | ||
616 | @PostConstruct | |
617 | public void init() { | |
618 | String offChainMetaDataRedisKey = getRedisKey(BOLNISI_METADATA_KEY + offChainMetadataUrl); | |
619 | String publicKeyRedisKey = getRedisKey(BOLNISI_METADATA_KEY + publicKeyPrimaryUrl); | |
620 | String publicKeyFallbackRedisKey = getRedisKey(BOLNISI_METADATA_KEY + publicKeyFallbackUrl); | |
621 | ||
622 | redisTemplate.delete(offChainMetaDataRedisKey); | |
623 | redisTemplate.delete(publicKeyRedisKey); | |
624 | redisTemplate.delete(publicKeyFallbackRedisKey); | |
625 | } | |
626 | } | |
Mutations | ||
80 |
1.1 |
|
81 |
1.1 |
|
84 |
1.1 |
|
92 |
1.1 |
|
93 |
1.1 |
|
95 |
1.1 |
|
97 |
1.1 |
|
107 |
1.1 |
|
111 |
1.1 |
|
113 |
1.1 2.2 |
|
115 |
1.1 |
|
116 |
1.1 |
|
122 |
1.1 |
|
123 |
1.1 |
|
125 |
1.1 |
|
130 |
1.1 |
|
131 |
1.1 |
|
132 |
1.1 |
|
143 |
1.1 |
|
144 |
1.1 |
|
145 |
1.1 |
|
148 |
1.1 |
|
153 |
1.1 2.2 |
|
158 |
1.1 |
|
159 |
1.1 |
|
164 |
1.1 |
|
165 |
1.1 |
|
166 |
1.1 |
|
168 |
1.1 |
|
169 |
1.1 |
|
171 |
1.1 |
|
178 |
1.1 2.2 |
|
181 |
1.1 |
|
182 |
1.1 |
|
185 |
1.1 2.2 |
|
194 |
1.1 2.2 |
|
197 |
1.1 |
|
198 |
1.1 |
|
199 |
1.1 |
|
201 |
1.1 2.2 |
|
208 |
1.1 |
|
236 |
1.1 |
|
246 |
1.1 |
|
248 |
1.1 |
|
260 |
1.1 |
|
265 |
1.1 |
|
278 |
1.1 |
|
285 |
1.1 |
|
286 |
1.1 |
|
287 |
1.1 |
|
295 |
1.1 2.2 |
|
296 |
1.1 |
|
297 |
1.1 |
|
299 |
1.1 |
|
303 |
1.1 |
|
306 |
1.1 |
|
309 |
1.1 |
|
310 |
1.1 |
|
322 |
1.1 |
|
329 |
1.1 |
|
330 |
1.1 |
|
331 |
1.1 |
|
335 |
1.1 |
|
342 |
1.1 2.2 |
|
345 |
1.1 |
|
376 |
1.1 |
|
377 |
1.1 2.2 |
|
379 |
1.1 |
|
382 |
1.1 |
|
399 |
1.1 |
|
405 |
1.1 |
|
412 |
1.1 |
|
416 |
1.1 |
|
449 |
1.1 |
|
468 |
1.1 |
|
469 |
1.1 |
|
476 |
1.1 |
|
477 |
1.1 |
|
484 |
1.1 |
|
487 |
1.1 |
|
488 |
1.1 |
|
489 |
1.1 |
|
495 |
1.1 |
|
496 |
1.1 |
|
497 |
1.1 |
|
498 |
1.1 |
|
502 |
1.1 |
|
503 |
1.1 |
|
507 |
1.1 |
|
513 |
1.1 |
|
514 |
1.1 |
|
522 |
1.1 |
|
523 |
1.1 |
|
531 |
1.1 |
|
534 |
1.1 |
|
535 |
1.1 |
|
536 |
1.1 |
|
542 |
1.1 |
|
543 |
1.1 |
|
544 |
1.1 |
|
545 |
1.1 |
|
550 |
1.1 |
|
554 |
1.1 |
|
561 |
1.1 |
|
565 |
1.1 |
|
585 |
1.1 |
|
593 |
1.1 |
|
597 |
1.1 2.2 3.3 |
|
598 |
1.1 |
|
601 |
1.1 |
|
604 |
1.1 |
|
609 |
1.1 2.2 |
|
613 |
1.1 |