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

knowledgepixels / nanodash / 20263739355

16 Dec 2025 09:54AM UTC coverage: 15.457% (-0.1%) from 15.595%
20263739355

push

github

tkuhn
fix(Space): Synchronize ensureLoaded wait code

593 of 4976 branches covered (11.92%)

Branch coverage included in aggregate %.

1582 of 9095 relevant lines covered (17.39%)

2.26 hits per line

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

31.33
src/main/java/com/knowledgepixels/nanodash/Space.java
1
package com.knowledgepixels.nanodash;
2

3
import com.github.jsonldjava.shaded.com.google.common.collect.Ordering;
4
import com.google.common.collect.ArrayListMultimap;
5
import com.google.common.collect.Multimap;
6
import com.knowledgepixels.nanodash.template.Template;
7
import com.knowledgepixels.nanodash.template.TemplateData;
8
import com.knowledgepixels.nanodash.vocabulary.KPXL_TERMS;
9
import jakarta.xml.bind.DatatypeConverter;
10
import org.eclipse.rdf4j.model.IRI;
11
import org.eclipse.rdf4j.model.Literal;
12
import org.eclipse.rdf4j.model.Statement;
13
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
14
import org.eclipse.rdf4j.model.vocabulary.OWL;
15
import org.nanopub.Nanopub;
16
import org.nanopub.extra.services.ApiResponse;
17
import org.nanopub.extra.services.ApiResponseEntry;
18
import org.nanopub.extra.services.QueryRef;
19
import org.nanopub.vocabulary.NTEMPLATE;
20
import org.slf4j.Logger;
21
import org.slf4j.LoggerFactory;
22

23
import java.io.Serializable;
24
import java.util.*;
25

26
/**
27
 * Class representing a "Space", which can be any kind of collaborative unit, like a project, group, or event.
28
 */
29
public class Space extends ProfiledResource {
30

31
    private static final Logger logger = LoggerFactory.getLogger(Space.class);
9✔
32

33
    private static List<Space> spaceList;
34
    private static Map<String, List<Space>> spaceListByType;
35
    private static Map<String, Space> spacesByCoreInfo = new HashMap<>();
12✔
36
    private static Map<String, Space> spacesById;
37
    private static Map<Space, Set<Space>> subspaceMap;
38
    private static Map<Space, Set<Space>> superspaceMap;
39
    private static boolean loaded = false;
6✔
40
    private static Long runRootUpdateAfter = null;
9✔
41

42
    /**
43
     * Refresh the list of spaces from the API response.
44
     *
45
     * @param resp The API response containing space data.
46
     */
47
    public static synchronized void refresh(ApiResponse resp) {
48
        spaceList = new ArrayList<>();
12✔
49
        spaceListByType = new HashMap<>();
12✔
50
        Map<String, Space> prevSpacesByCoreInfoPrev = spacesByCoreInfo;
6✔
51
        spacesByCoreInfo = new HashMap<>();
12✔
52
        spacesById = new HashMap<>();
12✔
53
        subspaceMap = new HashMap<>();
12✔
54
        superspaceMap = new HashMap<>();
12✔
55
        for (ApiResponseEntry entry : resp.getData()) {
33✔
56
            Space space = new Space(entry);
15✔
57
            Space prevSpace = prevSpacesByCoreInfoPrev.get(space.getCoreInfoString());
18✔
58
            if (prevSpace != null) space = prevSpace;
6!
59
            spaceList.add(space);
12✔
60
            spaceListByType.computeIfAbsent(space.getType(), k -> new ArrayList<>()).add(space);
39✔
61
            spacesByCoreInfo.put(space.getCoreInfoString(), space);
18✔
62
            spacesById.put(space.getId(), space);
18✔
63
        }
3✔
64
        for (Space space : spaceList) {
30✔
65
            Space superSpace = space.getIdSuperspace();
9✔
66
            if (superSpace == null) continue;
9✔
67
            subspaceMap.computeIfAbsent(superSpace, k -> new HashSet<>()).add(space);
36✔
68
            superspaceMap.computeIfAbsent(space, k -> new HashSet<>()).add(superSpace);
36✔
69
        }
3✔
70
        loaded = true;
6✔
71
    }
3✔
72

73
    /**
74
     * Check if the spaces have been loaded.
75
     *
76
     * @return true if loaded, false otherwise.
77
     */
78
    public static boolean isLoaded() {
79
        return loaded;
×
80
    }
81

82
    public static boolean areAllSpacesInitialized() {
83
        for (Space space : spaceList) {
×
84
            if (!space.isDataInitialized()) return false;
×
85
        }
×
86
        return true;
×
87
    }
88

89
    @Override
90
    public boolean isDataInitialized() {
91
        triggerDataUpdate();
×
92
        return dataInitialized && super.isDataInitialized();
×
93
    }
94

95
    public static void triggerAllDataUpdates() {
96
        for (Space space : spaceList) {
×
97
            space.triggerDataUpdate();
×
98
        }
×
99
    }
×
100

101
    private static final String ensureLoadedLock = "";
102

103
    /**
104
     * Ensure that the spaces are loaded, fetching them from the API if necessary.
105
     */
106
    public static void ensureLoaded() {
107
        if (spaceList == null) {
6!
108
            try {
109
                synchronized (ensureLoadedLock) {
×
110
                    if (runRootUpdateAfter != null) {
×
111
                        while (System.currentTimeMillis() < runRootUpdateAfter) {
×
112
                            Thread.sleep(100);
×
113
                        }
114
                        runRootUpdateAfter = null;
×
115
                    }
116
                }
×
117
            } catch (InterruptedException ex) {
×
118
                logger.error("Interrupted", ex);
×
119
            }
×
120
            refresh(QueryApiAccess.forcedGet(new QueryRef("get-spaces")));
×
121
        }
122
    }
3✔
123

124
    public static void forceRootRefresh(long waitMillis) {
125
        spaceList = null;
×
126
        runRootUpdateAfter = System.currentTimeMillis() + waitMillis;
×
127
    }
×
128

129
    /**
130
     * Get the list of all spaces.
131
     *
132
     * @return List of spaces.
133
     */
134
    public static List<Space> getSpaceList() {
135
        ensureLoaded();
×
136
        return spaceList;
×
137
    }
138

139
    /**
140
     * Get the list of spaces of a specific type.
141
     *
142
     * @param type The type of spaces to retrieve.
143
     *             System.err.println("REFRESH...");
144
     * @return List of spaces of the specified type.
145
     */
146
    public static List<Space> getSpaceList(String type) {
147
        ensureLoaded();
×
148
        return spaceListByType.computeIfAbsent(type, k -> new ArrayList<>());
×
149
    }
150

151
    /**
152
     * Get a space by its id.
153
     *
154
     * @param id The id of the space.
155
     * @return The corresponding Space object, or null if not found.
156
     */
157
    public static Space get(String id) {
158
        ensureLoaded();
3✔
159
        return spacesById.get(id);
15✔
160
    }
161

162
    /**
163
     * Mark all spaces as needing a data update.
164
     */
165
    public static void refresh() {
166
        refresh(QueryApiAccess.forcedGet(new QueryRef("get-spaces")));
18✔
167
        for (Space space : spaceList) {
30✔
168
            space.dataNeedsUpdate = true;
9✔
169
        }
3✔
170
    }
3✔
171

172
    public void forceRefresh(long waitMillis) {
173
        super.forceRefresh(waitMillis);
×
174
        dataNeedsUpdate = true;
×
175
        dataInitialized = false;
×
176
    }
×
177

178
    private String label, rootNanopubId, type;
179
    private Nanopub rootNanopub = null;
9✔
180
    private SpaceData data = new SpaceData();
15✔
181

182
    private static class SpaceData implements Serializable {
6✔
183

184
        List<String> altIds = new ArrayList<>();
15✔
185

186
        String description = null;
9✔
187
        Calendar startDate, endDate;
188
        IRI defaultProvenance = null;
9✔
189

190
        List<IRI> admins = new ArrayList<>();
15✔
191
        Map<IRI, Set<SpaceMemberRoleRef>> users = new HashMap<>();
15✔
192
        List<SpaceMemberRoleRef> roles = new ArrayList<>();
15✔
193
        Map<IRI, SpaceMemberRole> roleMap = new HashMap<>();
15✔
194

195
        Map<String, IRI> adminPubkeyMap = new HashMap<>();
15✔
196
        Set<Serializable> pinnedResources = new HashSet<>();
15✔
197
        Set<String> pinGroupTags = new HashSet<>();
15✔
198
        Map<String, Set<Serializable>> pinnedResourceMap = new HashMap<>();
18✔
199

200
        void addAdmin(IRI admin, String npId) {
201
            // TODO This isn't efficient for long owner lists:
202
            if (admins.contains(admin)) return;
15!
203
            admins.add(admin);
15✔
204
            UserData ud = User.getUserData();
6✔
205
            for (String pubkeyhash : ud.getPubkeyhashes(admin, true)) {
42✔
206
                adminPubkeyMap.put(pubkeyhash, admin);
18✔
207
            }
3✔
208
            users.computeIfAbsent(admin, (k) -> new HashSet<>()).add(new SpaceMemberRoleRef(SpaceMemberRole.ADMIN_ROLE, npId));
51✔
209
        }
3✔
210

211
    }
212

213
    private boolean dataInitialized = false;
9✔
214
    private boolean dataNeedsUpdate = true;
9✔
215

216
    private Space(ApiResponseEntry resp) {
217
        super(resp.get("space"));
15✔
218
        initSpace(this);
9✔
219
        this.label = resp.get("label");
15✔
220
        this.type = resp.get("type");
15✔
221
        this.rootNanopubId = resp.get("np");
15✔
222
        this.rootNanopub = Utils.getAsNanopub(rootNanopubId);
15✔
223
        setCoreData(data);
12✔
224
    }
3✔
225

226
    /**
227
     * Get the root nanopublication ID of the space.
228
     *
229
     * @return The root nanopub ID.
230
     */
231
    @Override
232
    public String getNanopubId() {
233
        return rootNanopubId;
×
234
    }
235

236
    /**
237
     * Get a string combining the space ID and root nanopub ID for core identification.
238
     *
239
     * @return The core info string.
240
     */
241
    public String getCoreInfoString() {
242
        return getId() + " " + rootNanopubId;
18✔
243
    }
244

245
    /**
246
     * Get the root nanopublication of the space.
247
     *
248
     * @return The root Nanopub object.
249
     */
250
    @Override
251
    public Nanopub getNanopub() {
252
        return rootNanopub;
×
253
    }
254

255
    /**
256
     * Get the label of the space.
257
     *
258
     * @return The space label.
259
     */
260
    public String getLabel() {
261
        return label;
×
262
    }
263

264
    /**
265
     * Get the type of the space.
266
     *
267
     * @return The space type.
268
     */
269
    public String getType() {
270
        return type;
9✔
271
    }
272

273
    /**
274
     * Get the start date of the space.
275
     *
276
     * @return The start date as a Calendar object, or null if not set.
277
     */
278
    public Calendar getStartDate() {
279
        return data.startDate;
×
280
    }
281

282
    /**
283
     * Get the end date of the space.
284
     *
285
     * @return The end date as a Calendar object, or null if not set.
286
     */
287
    public Calendar getEndDate() {
288
        return data.endDate;
×
289
    }
290

291
    /**
292
     * Get a simplified label for the type of space by removing any namespace prefix.
293
     *
294
     * @return The simplified type label.
295
     */
296
    public String getTypeLabel() {
297
        return type.replaceFirst("^.*/", "");
×
298
    }
299

300
    /**
301
     * Get the description of the space.
302
     *
303
     * @return The description string.
304
     */
305
    public String getDescription() {
306
        return data.description;
×
307
    }
308

309

310
    /**
311
     * Get the list of admins in this space.
312
     *
313
     * @return List of admin IRIs.
314
     */
315
    public List<IRI> getAdmins() {
316
        ensureInitialized();
×
317
        return data.admins;
×
318
    }
319

320
    /**
321
     * Get the list of members in this space.
322
     *
323
     * @return List of member IRIs.
324
     */
325
    public List<IRI> getUsers() {
326
        ensureInitialized();
×
327
        List<IRI> users = new ArrayList<IRI>(data.users.keySet());
×
328
        users.sort(User.getUserData().userComparator);
×
329
        return users;
×
330
    }
331

332
    /**
333
     * Get the roles of a specific member in this space.
334
     *
335
     * @param userId The IRI of the member.
336
     * @return Set of roles assigned to the member, or null if the member is not part of this space.
337
     */
338
    public Set<SpaceMemberRoleRef> getMemberRoles(IRI userId) {
339
        ensureInitialized();
×
340
        return data.users.get(userId);
×
341
    }
342

343
    /**
344
     * Check if a user is a member of this space.
345
     *
346
     * @param userId The IRI of the user to check.
347
     * @return true if the user is a member, false otherwise.
348
     */
349
    public boolean isMember(IRI userId) {
350
        ensureInitialized();
×
351
        return data.users.containsKey(userId);
×
352
    }
353

354
    public boolean isAdminPubkey(String pubkey) {
355
        ensureInitialized();
×
356
        return data.adminPubkeyMap.containsKey(pubkey);
×
357
    }
358

359
    /**
360
     * Get the list of pinned resources in this space.
361
     *
362
     * @return List of pinned resources.
363
     */
364
    public Set<Serializable> getPinnedResources() {
365
        ensureInitialized();
×
366
        return data.pinnedResources;
×
367
    }
368

369
    /**
370
     * Get the set of tags used for grouping pinned resources.
371
     *
372
     * @return Set of tags.
373
     */
374
    public Set<String> getPinGroupTags() {
375
        ensureInitialized();
×
376
        return data.pinGroupTags;
×
377
    }
378

379
    /**
380
     * Get a map of pinned resources grouped by their tags.
381
     *
382
     * @return Map where keys are tags and values are lists of pinned resources (Templates or GrlcQueries).
383
     */
384
    public Map<String, Set<Serializable>> getPinnedResourceMap() {
385
        ensureInitialized();
×
386
        return data.pinnedResourceMap;
×
387
    }
388

389
    public boolean appliesTo(String elementId, Set<IRI> classes) {
390
        triggerDataUpdate();
×
391
        for (ViewDisplay v : getViewDisplays()) {
×
392
            if (v.appliesTo(elementId, classes)) return true;
×
393
        }
×
394
        return false;
×
395
    }
396

397
    /**
398
     * Get the default provenance IRI for this space.
399
     *
400
     * @return The default provenance IRI, or null if not set.
401
     */
402
    public IRI getDefaultProvenance() {
403
        return data.defaultProvenance;
×
404
    }
405

406
    /**
407
     * Get the roles defined in this space.
408
     *
409
     * @return List of roles.
410
     */
411
    public List<SpaceMemberRoleRef> getRoles() {
412
        return data.roles;
×
413
    }
414

415
    /**
416
     * Get the super ID of the space.
417
     *
418
     * @return Always returns null. Use getIdSuperspace() instead.
419
     */
420
    public String getSuperId() {
421
        return null;
×
422
    }
423

424
    /**
425
     * Get the superspace ID.
426
     *
427
     * @return The superspace, or null if not applicable.
428
     */
429
    public Space getIdSuperspace() {
430
        if (!getId().matches("https?://[^/]+/.*/[^/]*/?")) return null;
15!
431
        String superId = getId().replaceFirst("(https?://[^/]+/.*)/[^/]*/?", "$1");
18✔
432
        if (spacesById.containsKey(superId)) {
12✔
433
            return spacesById.get(superId);
15✔
434
        }
435
        return null;
6✔
436
    }
437

438
    /**
439
     * Get superspaces of this space.
440
     *
441
     * @return List of superspaces.
442
     */
443
    public List<Space> getSuperspaces() {
444
        if (superspaceMap.containsKey(this)) {
×
445
            List<Space> superspaces = new ArrayList<>(superspaceMap.get(this));
×
446
            Collections.sort(superspaces, Ordering.usingToString());
×
447
            return superspaces;
×
448
        }
449
        return new ArrayList<>();
×
450
    }
451

452
    /**
453
     * Get subspaces of this space.
454
     *
455
     * @return List of subspaces.
456
     */
457
    public List<Space> getSubspaces() {
458
        if (subspaceMap.containsKey(this)) {
×
459
            List<Space> subspaces = new ArrayList<>(subspaceMap.get(this));
×
460
            Collections.sort(subspaces, Ordering.usingToString());
×
461
            return subspaces;
×
462
        }
463
        return new ArrayList<>();
×
464
    }
465

466
    /**
467
     * Get subspaces of a specific type.
468
     *
469
     * @param type The type of subspaces to retrieve.
470
     * @return List of subspaces of the specified type.
471
     */
472
    public List<Space> getSubspaces(String type) {
473
        List<Space> l = new ArrayList<>();
×
474
        for (Space s : getSubspaces()) {
×
475
            if (s.getType().equals(type)) l.add(s);
×
476
        }
×
477
        return l;
×
478
    }
479

480
    /**
481
     * Get alternative IDs for the space.
482
     *
483
     * @return List of alternative IDs.
484
     */
485
    public List<String> getAltIDs() {
486
        return data.altIds;
×
487
    }
488

489
    private synchronized void ensureInitialized() {
490
        Thread thread = triggerSpaceDataUpdate();
×
491
        if (!dataInitialized && thread != null) {
×
492
            try {
493
                thread.join();
×
494
            } catch (InterruptedException ex) {
×
495
                logger.error("failed to join thread", ex);
×
496
            }
×
497
        }
498
        thread = super.triggerDataUpdate();
×
499
        if (!dataInitialized && thread != null) {
×
500
            try {
501
                thread.join();
×
502
            } catch (InterruptedException ex) {
×
503
                logger.error("failed to join thread", ex);
×
504
            }
×
505
        }
506
    }
×
507

508
    @Override
509
    protected synchronized Thread triggerDataUpdate() {
510
        triggerSpaceDataUpdate();
×
511
        return super.triggerDataUpdate();
×
512
    }
513

514
    private synchronized Thread triggerSpaceDataUpdate() {
515
        if (dataNeedsUpdate) {
×
516
            Thread thread = new Thread(() -> {
×
517
                try {
518
                    if (getRunUpdateAfter() != null) {
×
519
                        while (System.currentTimeMillis() < getRunUpdateAfter()) {
×
520
                            Thread.sleep(100);
×
521
                        }
522
                    }
523
                    SpaceData newData = new SpaceData();
×
524
                    setCoreData(newData);
×
525

526
                    newData.roles.add(new SpaceMemberRoleRef(SpaceMemberRole.ADMIN_ROLE, null));
×
527
                    newData.roleMap.put(KPXL_TERMS.HAS_ADMIN_PREDICATE, SpaceMemberRole.ADMIN_ROLE);
×
528

529
                    // TODO Improve this:
530
                    Multimap<String, String> spaceIds = ArrayListMultimap.create();
×
531
                    Multimap<String, String> resourceIds = ArrayListMultimap.create();
×
532
                    spaceIds.put("space", getId());
×
533
                    resourceIds.put("resource", getId());
×
534
                    for (String id : newData.altIds) {
×
535
                        spaceIds.put("space", id);
×
536
                        resourceIds.put("resource", id);
×
537
                    }
×
538

539
                    ApiResponse getAdminsResponse = QueryApiAccess.get(new QueryRef("get-admins", spaceIds));
×
540
                    boolean continueAddingAdmins = true;
×
541
                    while (continueAddingAdmins) {
×
542
                        continueAddingAdmins = false;
×
543
                        for (ApiResponseEntry r : getAdminsResponse.getData()) {
×
544
                            String pubkeyhash = r.get("pubkey");
×
545
                            if (newData.adminPubkeyMap.containsKey(pubkeyhash)) {
×
546
                                IRI adminId = Utils.vf.createIRI(r.get("admin"));
×
547
                                if (!newData.admins.contains(adminId)) {
×
548
                                    continueAddingAdmins = true;
×
549
                                    newData.addAdmin(adminId, r.get("np"));
×
550
                                }
551
                            }
552
                        }
×
553
                    }
554
                    newData.admins.sort(User.getUserData().userComparator);
×
555

556
                    Multimap<String, String> getSpaceMemberParams = ArrayListMultimap.create(spaceIds);
×
557

558
                    for (ApiResponseEntry r : QueryApiAccess.get(new QueryRef("get-space-member-roles", spaceIds)).getData()) {
×
559
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
560
                        SpaceMemberRole role = new SpaceMemberRole(r);
×
561
                        newData.roles.add(new SpaceMemberRoleRef(role, r.get("np")));
×
562

563
                        // TODO Handle cases of overlapping properties:
564
                        for (IRI p : role.getRegularProperties()) newData.roleMap.put(p, role);
×
565
                        for (IRI p : role.getInverseProperties()) newData.roleMap.put(p, role);
×
566

567
                        role.addRoleParams(getSpaceMemberParams);
×
568
                    }
×
569

570
                    for (ApiResponseEntry r : QueryApiAccess.get(new QueryRef("get-space-members", getSpaceMemberParams)).getData()) {
×
571
                        IRI memberId = Utils.vf.createIRI(r.get("member"));
×
572
                        SpaceMemberRole role = newData.roleMap.get(Utils.vf.createIRI(r.get("role")));
×
573
                        newData.users.computeIfAbsent(memberId, (k) -> new HashSet<>()).add(new SpaceMemberRoleRef(role, r.get("np")));
×
574
                    }
×
575

576
                    for (ApiResponseEntry r : QueryApiAccess.get(new QueryRef("get-pinned-templates", spaceIds)).getData()) {
×
577
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
578
                        Template t = TemplateData.get().getTemplate(r.get("template"));
×
579
                        if (t == null) continue;
×
580
                        newData.pinnedResources.add(t);
×
581
                        String tag = r.get("tag");
×
582
                        if (tag != null && !tag.isEmpty()) {
×
583
                            newData.pinGroupTags.add(r.get("tag"));
×
584
                            newData.pinnedResourceMap.computeIfAbsent(tag, k -> new HashSet<>()).add(TemplateData.get().getTemplate(r.get("template")));
×
585
                        }
586
                    }
×
587
                    for (ApiResponseEntry r : QueryApiAccess.get(new QueryRef("get-pinned-queries", spaceIds)).getData()) {
×
588
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
589
                        GrlcQuery query = GrlcQuery.get(r.get("query"));
×
590
                        if (query == null) continue;
×
591
                        newData.pinnedResources.add(query);
×
592
                        String tag = r.get("tag");
×
593
                        if (tag != null && !tag.isEmpty()) {
×
594
                            newData.pinGroupTags.add(r.get("tag"));
×
595
                            newData.pinnedResourceMap.computeIfAbsent(tag, k -> new HashSet<>()).add(query);
×
596
                        }
597
                    }
×
598
                    data = newData;
×
599
                    dataInitialized = true;
×
600
                } catch (Exception ex) {
×
601
                    logger.error("Error while trying to update space data: {}", ex);
×
602
                }
×
603
            });
×
604
            thread.start();
×
605
            dataNeedsUpdate = false;
×
606
            return thread;
×
607
        }
608
        return null;
×
609
    }
610

611
    private void setCoreData(SpaceData data) {
612
        for (Statement st : rootNanopub.getAssertion()) {
36✔
613
            if (st.getSubject().stringValue().equals(getId())) {
21!
614
                if (st.getPredicate().equals(OWL.SAMEAS) && st.getObject() instanceof IRI objIri) {
42!
615
                    data.altIds.add(objIri.stringValue());
21✔
616
                } else if (st.getPredicate().equals(DCTERMS.DESCRIPTION)) {
15✔
617
                    data.description = st.getObject().stringValue();
18✔
618
                } else if (st.getPredicate().stringValue().equals("http://schema.org/startDate")) {
18✔
619
                    try {
620
                        data.startDate = DatatypeConverter.parseDateTime(st.getObject().stringValue());
18✔
621
                    } catch (IllegalArgumentException ex) {
×
622
                        logger.error("Failed to parse date {}", st.getObject().stringValue());
×
623
                    }
3✔
624
                } else if (st.getPredicate().stringValue().equals("http://schema.org/endDate")) {
18✔
625
                    try {
626
                        data.endDate = DatatypeConverter.parseDateTime(st.getObject().stringValue());
18✔
627
                    } catch (IllegalArgumentException ex) {
×
628
                        logger.error("Failed to parse date {}", st.getObject().stringValue());
×
629
                    }
3✔
630
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_ADMIN) && st.getObject() instanceof IRI obj) {
42!
631
                    data.addAdmin(obj, rootNanopub.getUri().stringValue());
24✔
632
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_PINNED_TEMPLATE) && st.getObject() instanceof IRI obj) {
15!
633
                    data.pinnedResources.add(TemplateData.get().getTemplate(obj.stringValue()));
×
634
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_PINNED_QUERY) && st.getObject() instanceof IRI obj) {
15!
635
                    data.pinnedResources.add(GrlcQuery.get(obj.stringValue()));
×
636
                } else if (st.getPredicate().equals(NTEMPLATE.HAS_DEFAULT_PROVENANCE) && st.getObject() instanceof IRI obj) {
15!
637
                    data.defaultProvenance = obj;
3✔
638
                }
639
            } else if (st.getPredicate().equals(NTEMPLATE.HAS_TAG) && st.getObject() instanceof Literal l) {
×
640
                data.pinGroupTags.add(l.stringValue());
×
641
                Set<Serializable> list = data.pinnedResourceMap.get(l.stringValue());
×
642
                if (list == null) {
×
643
                    list = new HashSet<>();
×
644
                    data.pinnedResourceMap.put(l.stringValue(), list);
×
645
                }
646
                list.add(TemplateData.get().getTemplate(st.getSubject().stringValue()));
×
647
            }
648
        }
3✔
649
    }
3✔
650

651
}
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