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

knowledgepixels / nanodash / 19772182304

28 Nov 2025 07:14PM UTC coverage: 13.901% (-0.2%) from 14.051%
19772182304

push

github

tkuhn
feat(UserPage): Add support for view displays

525 of 4894 branches covered (10.73%)

Branch coverage included in aggregate %.

1398 of 8940 relevant lines covered (15.64%)

0.69 hits per line

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

32.93
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.apache.commons.lang3.tuple.Pair;
11
import org.eclipse.rdf4j.model.IRI;
12
import org.eclipse.rdf4j.model.Literal;
13
import org.eclipse.rdf4j.model.Statement;
14
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
15
import org.eclipse.rdf4j.model.vocabulary.OWL;
16
import org.nanopub.Nanopub;
17
import org.nanopub.extra.services.ApiResponse;
18
import org.nanopub.extra.services.ApiResponseEntry;
19
import org.nanopub.extra.services.QueryRef;
20
import org.nanopub.vocabulary.NTEMPLATE;
21
import org.slf4j.Logger;
22
import org.slf4j.LoggerFactory;
23

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

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

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

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

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

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

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

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

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

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

121
    public static void forceRootRefresh(long waitMillis) {
122
        spaceList = null;
×
123
        runRootUpdateAfter = System.currentTimeMillis() + waitMillis;
×
124
    }
×
125

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

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

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

159
    /**
160
     * Mark all spaces as needing a data update.
161
     */
162
    public static void refresh() {
163
        refresh(QueryApiAccess.forcedGet(new QueryRef("get-spaces")));
6✔
164
        for (Space space : spaceList) {
10✔
165
            space.dataNeedsUpdate = true;
3✔
166
        }
1✔
167
    }
1✔
168

169
    public void forceRefresh(long waitMillis) {
170
        super.forceRefresh(waitMillis);
×
171
        dataNeedsUpdate = true;
×
172
        dataInitialized = false;
×
173
    }
×
174

175
    private String label, rootNanopubId, type;
176
    private Nanopub rootNanopub = null;
3✔
177
    private SpaceData data = new SpaceData();
5✔
178

179
    private static class SpaceData implements Serializable {
2✔
180

181
        List<String> altIds = new ArrayList<>();
5✔
182

183
        String description = null;
3✔
184
        Calendar startDate, endDate;
185
        IRI defaultProvenance = null;
3✔
186

187
        List<IRI> admins = new ArrayList<>();
5✔
188
        // TODO Make Pair<SpaceMemberRole, String> a new class with SpaceMemberRole + nanopub URI
189
        Map<IRI, Set<Pair<SpaceMemberRole, String>>> users = new HashMap<>();
5✔
190
        List<Pair<SpaceMemberRole, String>> roles = new ArrayList<>();
5✔
191
        Map<IRI, SpaceMemberRole> roleMap = new HashMap<>();
5✔
192

193
        Map<String, IRI> adminPubkeyMap = new HashMap<>();
5✔
194
        Set<Serializable> pinnedResources = new HashSet<>();
5✔
195
        Set<String> pinGroupTags = new HashSet<>();
5✔
196
        Map<String, Set<Serializable>> pinnedResourceMap = new HashMap<>();
6✔
197

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

209
    }
210

211
    private boolean dataInitialized = false;
3✔
212
    private boolean dataNeedsUpdate = true;
3✔
213

214
    private Space(ApiResponseEntry resp) {
215
        super(resp.get("space"));
5✔
216
        initSpace(this);
3✔
217
        this.label = resp.get("label");
5✔
218
        this.type = resp.get("type");
5✔
219
        this.rootNanopubId = resp.get("np");
5✔
220
        this.rootNanopub = Utils.getAsNanopub(rootNanopubId);
5✔
221
        setCoreData(data);
4✔
222
    }
1✔
223

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

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

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

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

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

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

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

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

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

307

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

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

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

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

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

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

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

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

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

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

404
    /**
405
     * Get the roles defined in this space.
406
     *
407
     * @return List of roles.
408
     */
409
    public List<Pair<SpaceMemberRole, String>> getRoles() {
410
        return data.roles;
×
411
    }
412

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

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

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

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

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

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

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

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

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

524
                    newData.roles.add(Pair.of(SpaceMemberRole.ADMIN_ROLE, null));
×
525
                    newData.roleMap.put(KPXL_TERMS.HAS_ADMIN_PREDICATE, SpaceMemberRole.ADMIN_ROLE);
×
526

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

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

554
                    Multimap<String, String> getSpaceMemberParams = ArrayListMultimap.create(spaceIds);
×
555

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

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

565
                        role.addRoleParams(getSpaceMemberParams);
×
566
                    }
×
567

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

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

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

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