• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

knowledgepixels / nanodash / 20299457275

17 Dec 2025 10:20AM UTC coverage: 14.401% (-0.9%) from 15.279%
20299457275

push

github

tkuhn
fix: Use API result cache for all requests

546 of 5004 branches covered (10.91%)

Branch coverage included in aggregate %.

1496 of 9176 relevant lines covered (16.3%)

2.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

34.7
src/main/java/com/knowledgepixels/nanodash/UserData.java
1
package com.knowledgepixels.nanodash;
2

3
import java.io.IOException;
4
import java.io.Serializable;
5
import java.util.ArrayList;
6
import java.util.Calendar;
7
import java.util.Comparator;
8
import java.util.HashMap;
9
import java.util.HashSet;
10
import java.util.List;
11
import java.util.Map;
12
import java.util.Set;
13

14
import org.eclipse.rdf4j.common.exception.RDF4JException;
15
import org.eclipse.rdf4j.model.IRI;
16
import org.eclipse.rdf4j.model.ValueFactory;
17
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
18
import org.nanopub.MalformedNanopubException;
19
import org.nanopub.Nanopub;
20
import org.nanopub.SimpleTimestampPattern;
21
import org.nanopub.extra.security.MalformedCryptoElementException;
22
import org.nanopub.extra.security.NanopubSignatureElement;
23
import org.nanopub.extra.security.SignatureUtils;
24
import org.nanopub.extra.server.GetNanopub;
25
import org.nanopub.extra.services.ApiResponseEntry;
26
import org.nanopub.extra.services.QueryRef;
27
import org.nanopub.extra.setting.IntroNanopub;
28
import org.nanopub.extra.setting.NanopubSetting;
29
import org.nanopub.vocabulary.NPX;
30
import org.slf4j.Logger;
31
import org.slf4j.LoggerFactory;
32

33
/**
34
 * UserData class manages user-related data.
35
 */
36
public class UserData implements Serializable {
37

38
    private static ValueFactory vf = SimpleValueFactory.getInstance();
6✔
39
    private static final Logger logger = LoggerFactory.getLogger(UserData.class);
12✔
40

41
    private HashMap<IRI, Set<String>> approvedIdPubkeyhashMap = new HashMap<>();
15✔
42
    private HashMap<String, Set<IRI>> approvedPubkeyhashIdMap = new HashMap<>();
15✔
43
    private HashMap<String, Set<IRI>> approvedPubkeyhashLocationMap = new HashMap<>();
15✔
44
    private HashMap<IRI, Set<String>> unapprovedIdPubkeyhashMap = new HashMap<>();
15✔
45
    private HashMap<String, Set<IRI>> unapprovedPubkeyhashIdMap = new HashMap<>();
15✔
46
    private HashMap<String, Set<IRI>> unapprovedPubkeyhashLocationMap = new HashMap<>();
15✔
47
    private HashMap<String, Set<IRI>> pubkeyhashIntroMap = new HashMap<>();
15✔
48
    private HashMap<IRI, IntroNanopub> introMap = new HashMap<>();
15✔
49
    private Set<IRI> approvedIntros = new HashSet<>();
15✔
50
    private HashMap<IRI, String> idNameMap = new HashMap<>();
15✔
51
    private HashMap<IRI, List<IntroNanopub>> introNanopubLists = new HashMap<>();
15✔
52

53
    /**
54
     * Default constructor for UserData.
55
     * Initializes the user data by fetching nanopublications settings.
56
     */
57
    UserData() {
6✔
58
        final NanodashPreferences pref = NanodashPreferences.get();
6✔
59

60
        // TODO Make nanopublication setting configurable:
61
        NanopubSetting setting;
62
        if (pref.getSettingUri() != null) {
9!
63
            setting = new NanopubSetting(GetNanopub.get(pref.getSettingUri()));
×
64
        } else {
65
            try {
66
                setting = NanopubSetting.getLocalSetting();
6✔
67
            } catch (RDF4JException | MalformedNanopubException | IOException ex) {
×
68
                throw new RuntimeException(ex);
×
69
            }
3✔
70
        }
71
        String settingId = setting.getNanopub().getUri().stringValue();
15✔
72
        if (setting.getUpdateStrategy().equals(NPX.UPDATES_BY_CREATOR)) {
15!
73
            settingId = QueryApiAccess.getLatestVersionId(settingId);
9✔
74
            setting = new NanopubSetting(GetNanopub.get(settingId));
18✔
75
        }
76
        logger.info("Using nanopublication setting: {}", settingId);
12✔
77

78
//                // Get users that are listed directly in the authority index, and consider them approved:
79
//                ByteArrayOutputStream out = new ByteArrayOutputStream(); // TODO use piped out-in stream here
80
//                new FetchIndex(setting.getAgentIntroCollection().stringValue(), out, RDFFormat.TRIG, false, true, null).run();
81
//                InputStream in = new ByteArrayInputStream(out.toByteArray());
82
//                try {
83
//                        MultiNanopubRdfHandler.process(RDFFormat.TRIG, in, new MultiNanopubRdfHandler.NanopubHandler() {
84
//                                @Override
85
//                                public void handleNanopub(Nanopub np) {
86
//                                        // TODO: Check that latest version talks about same user
87
//                                        register(QueryApiAccess.getLatestVersionId(np.getUri().stringValue()), true);
88
//                                }
89
//                        });
90
//                } catch (RDFParseException | RDFHandlerException | IOException | MalformedNanopubException ex) {
91
//                        logger.error();
92
//                }
93
///
94
//                if (setting.getTrustRangeAlgorithm().equals(NPX.TRANSITIVE_TRUST)) {
95
//                        ApiResponse resp = QueryApiAccess.forcedGet("get-approved-nanopubs");
96
//                        List<ApiResponseEntry> results = new ArrayList<>(resp.getData());
97
//                        while (true) {
98
//                                boolean keepLooping = false;
99
//                                for (ApiResponseEntry entry : new ArrayList<>(results)) {
100
//                                        if (hasValue(approvedPubkeyIdMap, entry.get("pubkey"), Utils.vf.createIRI(entry.get("approver")))) {
101
//                                                register(entry.get("approved_np"), true);
102
//                                                results.remove(entry);
103
//                                                keepLooping = true;
104
//                                        }
105
//                                }
106
//                                if (!keepLooping) break;
107
//                        }
108
//                }
109

110
        logger.info("Loading approved users...");
9✔
111
        try {
112
            for (RegistryAccountInfo rai : RegistryAccountInfo.fromUrl(Utils.getMainRegistryUrl() + "list.json")) {
36✔
113
                registerApproved(rai);
9✔
114
            }
3✔
115
        } catch (Exception ex) {
×
116
            throw new RuntimeException(ex);
×
117
        }
3✔
118

119
        logger.info("Loading user details...");
9✔
120
        // Get latest introductions for all users, including unapproved ones:
121
        for (ApiResponseEntry entry : ApiCache.retrieveResponseSync(new QueryRef("get-all-user-intros"), true).getData()) {
48✔
122
            register(entry);
9✔
123
        }
3✔
124
    }
3✔
125

126
    private IntroNanopub toIntroNanopub(IRI iri) {
127
        if (iri == null) return null;
×
128
        if (introMap.containsKey(iri)) return introMap.get(iri);
×
129
        Nanopub np = Utils.getNanopub(iri.stringValue());
×
130
        if (np == null) return null;
×
131
        IntroNanopub introNp = new IntroNanopub(np);
×
132
        introMap.put(np.getUri(), introNp);
×
133
        return introNp;
×
134
    }
135

136
    private void registerApproved(RegistryAccountInfo rai) {
137
        if (rai.getAgent().equals("$")) return;
18✔
138
        addValue(approvedIdPubkeyhashMap, rai.getAgentIri(), rai.getPubkey());
24✔
139
        addValue(approvedPubkeyhashIdMap, rai.getPubkey(), rai.getAgentIri());
24✔
140
    }
3✔
141

142
    private void register(ApiResponseEntry entry) {
143
        IRI userIri;
144
        try {
145
            userIri = vf.createIRI(entry.get("user"));
18✔
146
        } catch (IllegalArgumentException ex) {
×
147
            logger.error("Error creating IRI from user string: {}", entry.get("user"), ex);
×
148
            return;
×
149
        }
3✔
150
        String pubkeyhash = entry.get("pubkeyHash");
12✔
151
        boolean approved = approvedIdPubkeyhashMap.containsKey(userIri) && approvedIdPubkeyhashMap.get(userIri).contains(pubkeyhash);
51✔
152
        boolean authoritative = "true".equals(entry.get("authoritative"));
18✔
153
        IRI introNpIri = null;
6✔
154
        try {
155
            introNpIri = vf.createIRI(entry.get("intronp"));
18✔
156
        } catch (IllegalArgumentException ex) {
×
157
            logger.error("Error creating IRI from intronp string: {}", entry.get("intronp"), ex);
×
158
        }
3✔
159
        IRI keyLocation = null;
6✔
160
        try {
161
            if (!entry.get("keyLocation").isEmpty()) {
15✔
162
                keyLocation = vf.createIRI(entry.get("keyLocation"));
18✔
163
            }
164
        } catch (IllegalArgumentException ex) {
×
165
            logger.error("Error creating IRI from keyLocation string: {}", entry.get("keyLocation"), ex);
×
166
        }
3✔
167
        if (approved) {
6✔
168
            if (authoritative) {
6✔
169
                if (introNpIri != null) approvedIntros.add(introNpIri);
21!
170
                if (keyLocation != null) addValue(approvedPubkeyhashLocationMap, pubkeyhash, keyLocation);
27✔
171
            }
172
        } else {
173
            addValue(unapprovedIdPubkeyhashMap, userIri, entry.get("pubkeyHash"));
24✔
174
            addValue(unapprovedPubkeyhashIdMap, entry.get("pubkeyHash"), userIri);
24✔
175
            if (keyLocation != null) addValue(unapprovedPubkeyhashLocationMap, pubkeyhash, keyLocation);
24✔
176
        }
177
        if (introNpIri != null) {
6!
178
            addValue(pubkeyhashIntroMap, entry.get("pubkeyHash"), introNpIri);
24✔
179
        }
180
        String name = entry.get("name");
12✔
181
        if (!name.isEmpty() && !idNameMap.containsKey(userIri)) {
24✔
182
            idNameMap.put(userIri, name);
18✔
183
        }
184
    }
3✔
185

186
/*
187
    private void register(String npId, boolean approved) {
188
        if (!TrustyUriUtils.isPotentialTrustyUri(npId)) return;
189
        IntroNanopub introNp = toIntroNanopub(npId);
190
        if (introNp == null) {
191
            //logger.error("No latest version of introduction found");
192
            return;
193
        }
194
        if (introNp.getUser() == null) {
195
            //logger.error("No identifier found in introduction");
196
            return;
197
        }
198
        if (introNp.getKeyDeclarations().isEmpty()) {
199
            //logger.error("No key declarations found in introduction");
200
            return;
201
        }
202
        if (approved) {
203
            approvedIntroMap.put(introNp.getNanopub().getUri(), introNp);
204
        }
205
        String userId = introNp.getUser().stringValue();
206
        IRI userIri = Utils.vf.createIRI(userId);
207
        if (userId.startsWith("https://orcid.org/")) {
208
            // Some simple ORCID ID wellformedness check:
209
            if (!userId.matches("https://orcid.org/[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{3}[0-9X]")) return;
210
        }
211
        for (KeyDeclaration kd : introNp.getKeyDeclarations()) {
212
            String pubkey = kd.getPublicKeyString();
213
            IRI keyLocation = kd.getKeyLocation();
214
            if (approved) {
215
                addValue(approvedIdPubkeyMap, userIri, pubkey);
216
                addValue(approvedPubkeyIdMap, pubkey, userIri);
217
                if (keyLocation != null) addValue(approvedPubkeyLocationMap, pubkey, keyLocation);
218
            } else {
219
                if (!hasValue(approvedIdPubkeyMap, userIri, pubkey)) {
220
                    addValue(unapprovedIdPubkeyMap, userIri, pubkey);
221
                    addValue(unapprovedPubkeyIdMap, pubkey, userIri);
222
                    if (keyLocation != null) addValue(unapprovedPubkeyLocationMap, pubkey, keyLocation);
223
                }
224
                addValue(pubkeyIntroMap, pubkey, introNp.getNanopub().getUri());
225
            }
226
        }
227
        if (!idNameMap.containsKey(userIri)) {
228
            idNameMap.put(userIri, introNp.getName());
229
        }
230
    }
231
    */
232

233
    private void addValue(Map<IRI, Set<String>> map, IRI key, String value) {
234
        Set<String> values = map.get(key);
15✔
235
        if (values == null) {
6✔
236
            values = new HashSet<>();
12✔
237
            map.put(key, values);
15✔
238
        }
239
        values.add(value);
12✔
240
    }
3✔
241

242
    private void addValue(Map<String, Set<IRI>> map, String key, IRI value) {
243
        Set<IRI> values = map.get(key);
15✔
244
        if (values == null) {
6✔
245
            values = new HashSet<>();
12✔
246
            map.put(key, values);
15✔
247
        }
248
        values.add(value);
12✔
249
    }
3✔
250

251
    private boolean hasValue(Map<IRI, Set<String>> map, IRI key, String value) {
252
        Set<String> values = map.get(key);
×
253
        if (values == null) return false;
×
254
        return values.contains(value);
×
255
    }
256

257
//        private static boolean hasValue(Map<String,Set<IRI>> map, String key, IRI value) {
258
//                Set<IRI> values = map.get(key);
259
//                if (values == null) return false;
260
//                return values.contains(value);
261
//        }
262

263
    /**
264
     * Checks if the given IRI is a user identifier.
265
     *
266
     * @param userIri the IRI to check
267
     * @return true if the IRI is a user identifier, false otherwise
268
     */
269
    public boolean isUser(IRI userIri) {
270
        return approvedIdPubkeyhashMap.containsKey(userIri) || unapprovedIdPubkeyhashMap.containsKey(userIri);
×
271
    }
272

273
    /**
274
     * Checks if the given userId is a valid user identifier.
275
     *
276
     * @param userId the user identifier to check, must start with "https://" or "http://"
277
     * @return true if the userId is a valid user identifier, false otherwise
278
     */
279
    public boolean isUser(String userId) {
280
        if (!userId.startsWith("https://") && !userId.startsWith("http://")) return false;
×
281
        try {
282
            IRI userIri = Utils.vf.createIRI(userId);
×
283
            return approvedIdPubkeyhashMap.containsKey(userIri) || unapprovedIdPubkeyhashMap.containsKey(userIri);
×
284
        } catch (IllegalArgumentException ex) {
×
285
            return false;
×
286
        }
287
    }
288

289
    /**
290
     * Checks if the given public key is approved for the specified user.
291
     *
292
     * @param pubkeyhash the public key to check
293
     * @param user       the IRI of the user to check against
294
     * @return true if the key is approved for the user, false otherwise
295
     */
296
    public boolean isApprovedPubkeyhashForUser(String pubkeyhash, IRI user) {
297
        return hasValue(approvedIdPubkeyhashMap, user, pubkeyhash);
×
298
    }
299

300
    private String getShortName(IRI userIri) {
301
        if (userIri == null) return "(unknown)";
×
302
        String n = userIri.stringValue();
×
303
        n = n.replaceFirst("^https://orcid.org/", "");
×
304
        if (n.length() > 40) return n.substring(0, 30) + "...";
×
305
        return n;
×
306
    }
307

308
    /**
309
     * Retrieves the IRI of a user based on their public key.
310
     *
311
     * @param pubkeyHash   the public key of the user
312
     * @param approvedOnly if true, only approved users are considered; if false, unapproved users are also considered
313
     * @return the IRI of the user if found, or null if not found
314
     */
315
    public IRI getUserIriForPubkeyhash(String pubkeyHash, boolean approvedOnly) {
316
        Set<IRI> userIris = approvedPubkeyhashIdMap.get(pubkeyHash);
×
317
        if (userIris != null && userIris.size() == 1) return userIris.iterator().next();
×
318
        if (!approvedOnly) {
×
319
            userIris = unapprovedPubkeyhashIdMap.get(pubkeyHash);
×
320
            if (userIris != null && userIris.size() == 1) return userIris.iterator().next();
×
321
        }
322
        return null;
×
323
    }
324

325
    /**
326
     * Retrieves the IRI of the owner of a nanopublication's signature.
327
     *
328
     * @param np the nanopublication
329
     * @return the IRI of the signature owner if found, or null if not found or if an error occurs
330
     */
331
    public IRI getSignatureOwnerIri(Nanopub np) {
332
        try {
333
            if (np != null) {
6!
334
                NanopubSignatureElement se = SignatureUtils.getSignatureElement(np);
9✔
335
                if (se != null) {
6!
336
                    String pubkeyhash = Utils.createSha256HexHash(se.getPublicKeyString());
×
337
                    return getUserIriForPubkeyhash(pubkeyhash, true);
×
338
                }
339
            }
340
        } catch (MalformedCryptoElementException ex) {
×
341
            logger.error("Error getting signature element", ex);
×
342
        }
3✔
343
        return null;
6✔
344
    }
345

346
    /**
347
     * Retrieves the name of a user based on their IRI.
348
     *
349
     * @param userIri the IRI of the user
350
     * @return the name of the user if found, or null if not found
351
     */
352
    public String getName(IRI userIri) {
353
        return idNameMap.get(userIri);
18✔
354
    }
355

356
    /**
357
     * Retrieves the display name of a user based on their IRI.
358
     *
359
     * @param userIri the IRI of the user
360
     * @return the display name of the user, which includes their name and short name
361
     */
362
    public String getDisplayName(IRI userIri) {
363
        String name = getName(userIri);
×
364
        if (name != null && !name.isEmpty()) {
×
365
            return name + " (" + getShortName(userIri) + ")";
×
366
        }
367
        return getShortName(userIri);
×
368
    }
369

370
    /**
371
     * Retrieves a short display name for a user based on their IRI.
372
     *
373
     * @param userIri the IRI of the user
374
     * @return the short display name of the user, which is either their name or their short name
375
     */
376
    public String getShortDisplayName(IRI userIri) {
377
        String name = getName(userIri);
×
378
        if (name != null && !name.isEmpty()) {
×
379
            return name;
×
380
        }
381
        return getShortName(userIri);
×
382
    }
383

384
    /**
385
     * Retrieves a short display name for a user based on their IRI and public key.
386
     *
387
     * @param userIri    the IRI of the user
388
     * @param pubkeyhash the public key of the user
389
     * @return the short display name of the user, which may include a contested identity note if multiple identities are associated with the public key
390
     */
391
    public String getShortDisplayNameForPubkeyhash(IRI userIri, String pubkeyhash) {
392
        Set<IRI> ids = approvedPubkeyhashIdMap.get(pubkeyhash);
×
393
        if (ids == null || ids.isEmpty()) {
×
394
            ids = unapprovedPubkeyhashIdMap.get(pubkeyhash);
×
395
            if (ids == null || ids.isEmpty()) {
×
396
                return getShortName(userIri);
×
397
            } else if (ids.size() == 1) {
×
398
                return getShortDisplayName(ids.iterator().next());
×
399
            } else {
400
                return getShortName(userIri) + " (contested identity)";
×
401
            }
402
        } else if (ids.size() == 1) {
×
403
            return getShortDisplayName(ids.iterator().next());
×
404
        } else {
405
            return "(contested identity)";
×
406
        }
407
    }
408

409
    /**
410
     * Finds a single user ID for a given public key.
411
     *
412
     * @param pubkeyhash the public key to search for
413
     * @return the IRI of the user if exactly one ID is found for the public key, or null if no ID or multiple IDs are found
414
     */
415
    public IRI findSingleIdForPubkeyhash(String pubkeyhash) {
416
        if (approvedPubkeyhashIdMap.containsKey(pubkeyhash) && !approvedPubkeyhashIdMap.get(pubkeyhash).isEmpty()) {
×
417
            if (approvedPubkeyhashIdMap.get(pubkeyhash).size() == 1) {
×
418
                return approvedPubkeyhashIdMap.get(pubkeyhash).iterator().next();
×
419
            } else {
420
                return null;
×
421
            }
422
        }
423
        if (unapprovedPubkeyhashIdMap.containsKey(pubkeyhash) && !unapprovedPubkeyhashIdMap.get(pubkeyhash).isEmpty()) {
×
424
            if (unapprovedPubkeyhashIdMap.get(pubkeyhash).size() == 1) {
×
425
                return unapprovedPubkeyhashIdMap.get(pubkeyhash).iterator().next();
×
426
            } else {
427
                return null;
×
428
            }
429
        }
430
        return null;
×
431
    }
432

433
    /**
434
     * Comparator for sorting users by their display names in a case-insensitive manner.
435
     */
436
    public final transient Comparator<IRI> userComparator = (iri1, iri2) -> getDisplayName(iri1).toLowerCase().compareTo(getDisplayName(iri2).toLowerCase());
12✔
437

438
    /**
439
     * Retrieves a list of users, either approved or unapproved.
440
     *
441
     * @param approved if true, retrieves approved users; if false, retrieves unapproved users
442
     * @return a sorted list of user IRIs
443
     */
444
    public List<IRI> getUsers(boolean approved) {
445
        List<IRI> list;
446
        if (approved) {
×
447
            list = new ArrayList<IRI>(approvedIdPubkeyhashMap.keySet());
×
448
        } else {
449
            list = new ArrayList<IRI>();
×
450
            for (IRI u : unapprovedIdPubkeyhashMap.keySet()) {
×
451
                if (!approvedIdPubkeyhashMap.containsKey(u)) list.add(u);
×
452
            }
×
453
        }
454
        // TODO Cache the sorted list to not sort from scratch each time:
455
        list.sort(userComparator);
×
456
        return list;
×
457
    }
458

459
    /**
460
     * Retrieves a list of public keys for a given user.
461
     *
462
     * @param user     the IRI of the user whose public keys are to be retrieved
463
     * @param approved if true, retrieves approved public keys; if false, retrieves unapproved public keys
464
     * @return a list of public keys associated with the user, either approved or unapproved
465
     */
466
    public List<String> getPubkeyhashes(IRI user, Boolean approved) {
467
        List<String> pubkeys = new ArrayList<>();
12✔
468
        if (user != null) {
6!
469
            if (approved == null || approved) {
15!
470
                if (approvedIdPubkeyhashMap.containsKey(user)) pubkeys.addAll(approvedIdPubkeyhashMap.get(user));
39!
471
            }
472
            if (approved == null || !approved) {
15!
473
                if (unapprovedIdPubkeyhashMap.containsKey(user)) pubkeys.addAll(unapprovedIdPubkeyhashMap.get(user));
×
474
            }
475
        }
476
        return pubkeys;
6✔
477
    }
478

479
    /**
480
     * Retrieves a list of introduction nanopublications for a given user.
481
     *
482
     * @param user the IRI of the user whose introduction nanopublications are to be retrieved
483
     * @return a list of introduction nanopublications associated with the user, sorted by creation time
484
     */
485
    public List<IntroNanopub> getIntroNanopubs(IRI user) {
486
        if (introNanopubLists.containsKey(user)) return introNanopubLists.get(user);
×
487

488
        Map<IRI, IntroNanopub> introNps = new HashMap<>();
×
489
        if (approvedIdPubkeyhashMap.containsKey(user)) {
×
490
            for (String pk : approvedIdPubkeyhashMap.get(user)) {
×
491
                getIntroNanopubs(pk, introNps);
×
492
            }
×
493
        }
494
        if (unapprovedIdPubkeyhashMap.containsKey(user)) {
×
495
            for (String pk : unapprovedIdPubkeyhashMap.get(user)) {
×
496
                getIntroNanopubs(pk, introNps);
×
497
            }
×
498
        }
499
        List<IntroNanopub> list = new ArrayList<>(introNps.values());
×
500
        list.sort((i0, i1) -> {
×
501
            Calendar c0 = SimpleTimestampPattern.getCreationTime(i0.getNanopub());
×
502
            Calendar c1 = SimpleTimestampPattern.getCreationTime(i1.getNanopub());
×
503
            if (c0 == null && c1 == null) return 0;
×
504
            if (c0 == null) return 1;
×
505
            if (c1 == null) return -1;
×
506
            return -c0.compareTo(c1);
×
507
        });
508
        introNanopubLists.put(user, list);
×
509
        return list;
×
510
    }
511

512
    /**
513
     * Retrieves a map of introduction nanopublications for a given public key.
514
     *
515
     * @param pubkey the public key for which introduction nanopublications are to be retrieved
516
     * @return a map where the keys are IRI identifiers of introduction nanopublications and the values are the corresponding IntroNanopub objects
517
     */
518
    public Map<IRI, IntroNanopub> getIntroNanopubs(String pubkey) {
519
        Map<IRI, IntroNanopub> introNps = new HashMap<>();
×
520
        getIntroNanopubs(pubkey, introNps);
×
521
        return introNps;
×
522
    }
523

524
    private void getIntroNanopubs(String pubkeyhash, Map<IRI, IntroNanopub> introNps) {
525
        if (pubkeyhashIntroMap.containsKey(pubkeyhash)) {
×
526
            for (IRI iri : pubkeyhashIntroMap.get(pubkeyhash)) {
×
527
                IntroNanopub introNp = toIntroNanopub(iri);
×
528
                if (introNp != null) {
×
529
                    introNps.put(iri, introNp);
×
530
                }
531
            }
×
532
        }
533
    }
×
534

535
    /**
536
     * Checks if the given introduction nanopublication is approved.
537
     *
538
     * @param in the introduction nanopublication to check
539
     * @return true if the introduction nanopublication is approved, false otherwise
540
     */
541
    public boolean isApproved(IntroNanopub in) {
542
        return approvedIntros.contains(in.getNanopub().getUri());
×
543
    }
544

545
    /**
546
     * Retrieves the location of a public key.
547
     *
548
     * @param pubkeyhash the public key for which the location is to be retrieved
549
     * @return the IRI of the key location if found, or null if not found or if multiple locations are associated with the key
550
     */
551
    public IRI getKeyLocationForPubkeyhash(String pubkeyhash) {
552
        if (approvedPubkeyhashLocationMap.containsKey(pubkeyhash) && !approvedPubkeyhashLocationMap.get(pubkeyhash).isEmpty()) {
×
553
            if (approvedPubkeyhashLocationMap.get(pubkeyhash).size() == 1)
×
554
                return approvedPubkeyhashLocationMap.get(pubkeyhash).iterator().next();
×
555
            return null;
×
556
        }
557
        if (unapprovedPubkeyhashLocationMap.containsKey(pubkeyhash) && unapprovedPubkeyhashLocationMap.get(pubkeyhash).size() == 1) {
×
558
            return unapprovedPubkeyhashLocationMap.get(pubkeyhash).iterator().next();
×
559
        }
560
        return null;
×
561
    }
562

563
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc