• 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

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

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

13
import org.eclipse.rdf4j.model.IRI;
14
import org.eclipse.rdf4j.model.Literal;
15
import org.eclipse.rdf4j.model.Statement;
16
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
17
import org.eclipse.rdf4j.model.vocabulary.OWL;
18
import org.nanopub.Nanopub;
19
import org.nanopub.extra.services.ApiResponse;
20
import org.nanopub.extra.services.ApiResponseEntry;
21
import org.nanopub.extra.services.QueryRef;
22
import org.nanopub.vocabulary.NTEMPLATE;
23
import org.slf4j.Logger;
24
import org.slf4j.LoggerFactory;
25

26
import com.github.jsonldjava.shaded.com.google.common.collect.Ordering;
27
import com.google.common.collect.ArrayListMultimap;
28
import com.google.common.collect.Multimap;
29
import com.knowledgepixels.nanodash.template.Template;
30
import com.knowledgepixels.nanodash.template.TemplateData;
31
import com.knowledgepixels.nanodash.vocabulary.KPXL_TERMS;
32

33
import jakarta.xml.bind.DatatypeConverter;
34

35
/**
36
 * Class representing a "Space", which can be any kind of collaborative unit, like a project, group, or event.
37
 */
38
public class Space extends ProfiledResource {
39

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

42
    private static List<Space> spaceList;
43
    private static Map<String, List<Space>> spaceListByType;
44
    private static Map<String, Space> spacesByCoreInfo = new HashMap<>();
12✔
45
    private static Map<String, Space> spacesById;
46
    private static Map<Space, Set<Space>> subspaceMap;
47
    private static Map<Space, Set<Space>> superspaceMap;
48
    private static boolean loaded = false;
6✔
49
    private static Long runRootUpdateAfter = null;
9✔
50

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

82
    /**
83
     * Check if the spaces have been loaded.
84
     *
85
     * @return true if loaded, false otherwise.
86
     */
87
    public static boolean isLoaded() {
88
        return loaded;
×
89
    }
90

91
    public static boolean areAllSpacesInitialized() {
92
        for (Space space : spaceList) {
×
93
            if (!space.isDataInitialized()) return false;
×
94
        }
×
95
        return true;
×
96
    }
97

98
    @Override
99
    public boolean isDataInitialized() {
100
        triggerDataUpdate();
×
101
        return dataInitialized && super.isDataInitialized();
×
102
    }
103

104
    public static void triggerAllDataUpdates() {
105
        for (Space space : spaceList) {
×
106
            space.triggerDataUpdate();
×
107
        }
×
108
    }
×
109

110
    private static final String ensureLoadedLock = "";
111

112
    /**
113
     * Ensure that the spaces are loaded, fetching them from the API if necessary.
114
     */
115
    public static void ensureLoaded() {
116
        if (spaceList == null) {
6!
117
            try {
118
                synchronized (ensureLoadedLock) {
×
119
                    if (runRootUpdateAfter != null) {
×
120
                        while (System.currentTimeMillis() < runRootUpdateAfter) {
×
121
                            Thread.sleep(100);
×
122
                        }
123
                        runRootUpdateAfter = null;
×
124
                    }
125
                }
×
126
            } catch (InterruptedException ex) {
×
127
                logger.error("Interrupted", ex);
×
128
            }
×
129
            refresh(ApiCache.retrieveResponseSync(new QueryRef("get-spaces"), true));
×
130
        }
131
    }
3✔
132

133
    public static void forceRootRefresh(long waitMillis) {
134
        spaceList = null;
×
135
        runRootUpdateAfter = System.currentTimeMillis() + waitMillis;
×
136
    }
×
137

138
    /**
139
     * Get the list of all spaces.
140
     *
141
     * @return List of spaces.
142
     */
143
    public static List<Space> getSpaceList() {
144
        ensureLoaded();
×
145
        return spaceList;
×
146
    }
147

148
    /**
149
     * Get the list of spaces of a specific type.
150
     *
151
     * @param type The type of spaces to retrieve.
152
     *             System.err.println("REFRESH...");
153
     * @return List of spaces of the specified type.
154
     */
155
    public static List<Space> getSpaceList(String type) {
156
        ensureLoaded();
×
157
        return spaceListByType.computeIfAbsent(type, k -> new ArrayList<>());
×
158
    }
159

160
    /**
161
     * Get a space by its id.
162
     *
163
     * @param id The id of the space.
164
     * @return The corresponding Space object, or null if not found.
165
     */
166
    public static Space get(String id) {
167
        ensureLoaded();
3✔
168
        return spacesById.get(id);
15✔
169
    }
170

171
    /**
172
     * Mark all spaces as needing a data update.
173
     */
174
    public static void refresh() {
175
        refresh(ApiCache.retrieveResponseSync(new QueryRef("get-spaces"), true));
21✔
176
        for (Space space : spaceList) {
30✔
177
            space.dataNeedsUpdate = true;
9✔
178
        }
3✔
179
    }
3✔
180

181
    public void forceRefresh(long waitMillis) {
182
        super.forceRefresh(waitMillis);
×
183
        dataNeedsUpdate = true;
×
184
        dataInitialized = false;
×
185
    }
×
186

187
    private String label, rootNanopubId, type;
188
    private Nanopub rootNanopub = null;
9✔
189
    private SpaceData data = new SpaceData();
15✔
190

191
    private static class SpaceData implements Serializable {
6✔
192

193
        List<String> altIds = new ArrayList<>();
15✔
194

195
        String description = null;
9✔
196
        Calendar startDate, endDate;
197
        IRI defaultProvenance = null;
9✔
198

199
        List<IRI> admins = new ArrayList<>();
15✔
200
        Map<IRI, Set<SpaceMemberRoleRef>> users = new HashMap<>();
15✔
201
        List<SpaceMemberRoleRef> roles = new ArrayList<>();
15✔
202
        Map<IRI, SpaceMemberRole> roleMap = new HashMap<>();
15✔
203

204
        Map<String, IRI> adminPubkeyMap = new HashMap<>();
15✔
205
        Set<Serializable> pinnedResources = new HashSet<>();
15✔
206
        Set<String> pinGroupTags = new HashSet<>();
15✔
207
        Map<String, Set<Serializable>> pinnedResourceMap = new HashMap<>();
18✔
208

209
        void addAdmin(IRI admin, String npId) {
210
            // TODO This isn't efficient for long owner lists:
211
            if (admins.contains(admin)) return;
15!
212
            admins.add(admin);
15✔
213
            UserData ud = User.getUserData();
6✔
214
            for (String pubkeyhash : ud.getPubkeyhashes(admin, true)) {
42✔
215
                adminPubkeyMap.put(pubkeyhash, admin);
18✔
216
            }
3✔
217
            users.computeIfAbsent(admin, (k) -> new HashSet<>()).add(new SpaceMemberRoleRef(SpaceMemberRole.ADMIN_ROLE, npId));
51✔
218
        }
3✔
219

220
    }
221

222
    private boolean dataInitialized = false;
9✔
223
    private boolean dataNeedsUpdate = true;
9✔
224

225
    private Space(ApiResponseEntry resp) {
226
        super(resp.get("space"));
15✔
227
        initSpace(this);
9✔
228
        this.label = resp.get("label");
15✔
229
        this.type = resp.get("type");
15✔
230
        this.rootNanopubId = resp.get("np");
15✔
231
        this.rootNanopub = Utils.getAsNanopub(rootNanopubId);
15✔
232
        setCoreData(data);
12✔
233
    }
3✔
234

235
    /**
236
     * Get the root nanopublication ID of the space.
237
     *
238
     * @return The root nanopub ID.
239
     */
240
    @Override
241
    public String getNanopubId() {
242
        return rootNanopubId;
×
243
    }
244

245
    /**
246
     * Get a string combining the space ID and root nanopub ID for core identification.
247
     *
248
     * @return The core info string.
249
     */
250
    public String getCoreInfoString() {
251
        return getId() + " " + rootNanopubId;
18✔
252
    }
253

254
    /**
255
     * Get the root nanopublication of the space.
256
     *
257
     * @return The root Nanopub object.
258
     */
259
    @Override
260
    public Nanopub getNanopub() {
261
        return rootNanopub;
×
262
    }
263

264
    /**
265
     * Get the label of the space.
266
     *
267
     * @return The space label.
268
     */
269
    public String getLabel() {
270
        return label;
×
271
    }
272

273
    /**
274
     * Get the type of the space.
275
     *
276
     * @return The space type.
277
     */
278
    public String getType() {
279
        return type;
9✔
280
    }
281

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

291
    /**
292
     * Get the end date of the space.
293
     *
294
     * @return The end date as a Calendar object, or null if not set.
295
     */
296
    public Calendar getEndDate() {
297
        return data.endDate;
×
298
    }
299

300
    /**
301
     * Get a simplified label for the type of space by removing any namespace prefix.
302
     *
303
     * @return The simplified type label.
304
     */
305
    public String getTypeLabel() {
306
        return type.replaceFirst("^.*/", "");
×
307
    }
308

309
    /**
310
     * Get the description of the space.
311
     *
312
     * @return The description string.
313
     */
314
    public String getDescription() {
315
        return data.description;
×
316
    }
317

318

319
    /**
320
     * Get the list of admins in this space.
321
     *
322
     * @return List of admin IRIs.
323
     */
324
    public List<IRI> getAdmins() {
325
        ensureInitialized();
×
326
        return data.admins;
×
327
    }
328

329
    /**
330
     * Get the list of members in this space.
331
     *
332
     * @return List of member IRIs.
333
     */
334
    public List<IRI> getUsers() {
335
        ensureInitialized();
×
336
        List<IRI> users = new ArrayList<IRI>(data.users.keySet());
×
337
        users.sort(User.getUserData().userComparator);
×
338
        return users;
×
339
    }
340

341
    /**
342
     * Get the roles of a specific member in this space.
343
     *
344
     * @param userId The IRI of the member.
345
     * @return Set of roles assigned to the member, or null if the member is not part of this space.
346
     */
347
    public Set<SpaceMemberRoleRef> getMemberRoles(IRI userId) {
348
        ensureInitialized();
×
349
        return data.users.get(userId);
×
350
    }
351

352
    /**
353
     * Check if a user is a member of this space.
354
     *
355
     * @param userId The IRI of the user to check.
356
     * @return true if the user is a member, false otherwise.
357
     */
358
    public boolean isMember(IRI userId) {
359
        ensureInitialized();
×
360
        return data.users.containsKey(userId);
×
361
    }
362

363
    public boolean isAdminPubkey(String pubkey) {
364
        ensureInitialized();
×
365
        return data.adminPubkeyMap.containsKey(pubkey);
×
366
    }
367

368
    /**
369
     * Get the list of pinned resources in this space.
370
     *
371
     * @return List of pinned resources.
372
     */
373
    public Set<Serializable> getPinnedResources() {
374
        ensureInitialized();
×
375
        return data.pinnedResources;
×
376
    }
377

378
    /**
379
     * Get the set of tags used for grouping pinned resources.
380
     *
381
     * @return Set of tags.
382
     */
383
    public Set<String> getPinGroupTags() {
384
        ensureInitialized();
×
385
        return data.pinGroupTags;
×
386
    }
387

388
    /**
389
     * Get a map of pinned resources grouped by their tags.
390
     *
391
     * @return Map where keys are tags and values are lists of pinned resources (Templates or GrlcQueries).
392
     */
393
    public Map<String, Set<Serializable>> getPinnedResourceMap() {
394
        ensureInitialized();
×
395
        return data.pinnedResourceMap;
×
396
    }
397

398
    public boolean appliesTo(String elementId, Set<IRI> classes) {
399
        triggerDataUpdate();
×
400
        for (ViewDisplay v : getViewDisplays()) {
×
401
            if (v.appliesTo(elementId, classes)) return true;
×
402
        }
×
403
        return false;
×
404
    }
405

406
    /**
407
     * Get the default provenance IRI for this space.
408
     *
409
     * @return The default provenance IRI, or null if not set.
410
     */
411
    public IRI getDefaultProvenance() {
412
        return data.defaultProvenance;
×
413
    }
414

415
    /**
416
     * Get the roles defined in this space.
417
     *
418
     * @return List of roles.
419
     */
420
    public List<SpaceMemberRoleRef> getRoles() {
421
        return data.roles;
×
422
    }
423

424
    /**
425
     * Get the super ID of the space.
426
     *
427
     * @return Always returns null. Use getIdSuperspace() instead.
428
     */
429
    public String getSuperId() {
430
        return null;
×
431
    }
432

433
    /**
434
     * Get the superspace ID.
435
     *
436
     * @return The superspace, or null if not applicable.
437
     */
438
    public Space getIdSuperspace() {
439
        if (!getId().matches("https?://[^/]+/.*/[^/]*/?")) return null;
15!
440
        String superId = getId().replaceFirst("(https?://[^/]+/.*)/[^/]*/?", "$1");
18✔
441
        if (spacesById.containsKey(superId)) {
12✔
442
            return spacesById.get(superId);
15✔
443
        }
444
        return null;
6✔
445
    }
446

447
    /**
448
     * Get superspaces of this space.
449
     *
450
     * @return List of superspaces.
451
     */
452
    public List<Space> getSuperspaces() {
453
        if (superspaceMap.containsKey(this)) {
×
454
            List<Space> superspaces = new ArrayList<>(superspaceMap.get(this));
×
455
            Collections.sort(superspaces, Ordering.usingToString());
×
456
            return superspaces;
×
457
        }
458
        return new ArrayList<>();
×
459
    }
460

461
    /**
462
     * Get subspaces of this space.
463
     *
464
     * @return List of subspaces.
465
     */
466
    public List<Space> getSubspaces() {
467
        if (subspaceMap.containsKey(this)) {
×
468
            List<Space> subspaces = new ArrayList<>(subspaceMap.get(this));
×
469
            Collections.sort(subspaces, Ordering.usingToString());
×
470
            return subspaces;
×
471
        }
472
        return new ArrayList<>();
×
473
    }
474

475
    /**
476
     * Get subspaces of a specific type.
477
     *
478
     * @param type The type of subspaces to retrieve.
479
     * @return List of subspaces of the specified type.
480
     */
481
    public List<Space> getSubspaces(String type) {
482
        List<Space> l = new ArrayList<>();
×
483
        for (Space s : getSubspaces()) {
×
484
            if (s.getType().equals(type)) l.add(s);
×
485
        }
×
486
        return l;
×
487
    }
488

489
    /**
490
     * Get alternative IDs for the space.
491
     *
492
     * @return List of alternative IDs.
493
     */
494
    public List<String> getAltIDs() {
495
        return data.altIds;
×
496
    }
497

498
    private synchronized void ensureInitialized() {
499
        Thread thread = triggerSpaceDataUpdate();
×
500
        if (!dataInitialized && thread != null) {
×
501
            try {
502
                thread.join();
×
503
            } catch (InterruptedException ex) {
×
504
                logger.error("failed to join thread", ex);
×
505
            }
×
506
        }
507
        thread = super.triggerDataUpdate();
×
508
        if (!dataInitialized && thread != null) {
×
509
            try {
510
                thread.join();
×
511
            } catch (InterruptedException ex) {
×
512
                logger.error("failed to join thread", ex);
×
513
            }
×
514
        }
515
    }
×
516

517
    @Override
518
    protected synchronized Thread triggerDataUpdate() {
519
        triggerSpaceDataUpdate();
×
520
        return super.triggerDataUpdate();
×
521
    }
522

523
    private synchronized Thread triggerSpaceDataUpdate() {
524
        if (dataNeedsUpdate) {
×
525
            Thread thread = new Thread(() -> {
×
526
                try {
527
                    if (getRunUpdateAfter() != null) {
×
528
                        while (System.currentTimeMillis() < getRunUpdateAfter()) {
×
529
                            Thread.sleep(100);
×
530
                        }
531
                    }
532
                    SpaceData newData = new SpaceData();
×
533
                    setCoreData(newData);
×
534

535
                    newData.roles.add(new SpaceMemberRoleRef(SpaceMemberRole.ADMIN_ROLE, null));
×
536
                    newData.roleMap.put(KPXL_TERMS.HAS_ADMIN_PREDICATE, SpaceMemberRole.ADMIN_ROLE);
×
537

538
                    // TODO Improve this:
539
                    Multimap<String, String> spaceIds = ArrayListMultimap.create();
×
540
                    Multimap<String, String> resourceIds = ArrayListMultimap.create();
×
541
                    spaceIds.put("space", getId());
×
542
                    resourceIds.put("resource", getId());
×
543
                    for (String id : newData.altIds) {
×
544
                        spaceIds.put("space", id);
×
545
                        resourceIds.put("resource", id);
×
546
                    }
×
547

548
                    ApiResponse getAdminsResponse = ApiCache.retrieveResponseSync(new QueryRef("get-admins", spaceIds), false);
×
549
                    boolean continueAddingAdmins = true;
×
550
                    while (continueAddingAdmins) {
×
551
                        continueAddingAdmins = false;
×
552
                        for (ApiResponseEntry r : getAdminsResponse.getData()) {
×
553
                            String pubkeyhash = r.get("pubkey");
×
554
                            if (newData.adminPubkeyMap.containsKey(pubkeyhash)) {
×
555
                                IRI adminId = Utils.vf.createIRI(r.get("admin"));
×
556
                                if (!newData.admins.contains(adminId)) {
×
557
                                    continueAddingAdmins = true;
×
558
                                    newData.addAdmin(adminId, r.get("np"));
×
559
                                }
560
                            }
561
                        }
×
562
                    }
563
                    newData.admins.sort(User.getUserData().userComparator);
×
564

565
                    Multimap<String, String> getSpaceMemberParams = ArrayListMultimap.create(spaceIds);
×
566

567
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-space-member-roles", spaceIds), false).getData()) {
×
568
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
569
                        SpaceMemberRole role = new SpaceMemberRole(r);
×
570
                        newData.roles.add(new SpaceMemberRoleRef(role, r.get("np")));
×
571

572
                        // TODO Handle cases of overlapping properties:
573
                        for (IRI p : role.getRegularProperties()) newData.roleMap.put(p, role);
×
574
                        for (IRI p : role.getInverseProperties()) newData.roleMap.put(p, role);
×
575

576
                        role.addRoleParams(getSpaceMemberParams);
×
577
                    }
×
578

579
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-space-members", getSpaceMemberParams), false).getData()) {
×
580
                        IRI memberId = Utils.vf.createIRI(r.get("member"));
×
581
                        SpaceMemberRole role = newData.roleMap.get(Utils.vf.createIRI(r.get("role")));
×
582
                        newData.users.computeIfAbsent(memberId, (k) -> new HashSet<>()).add(new SpaceMemberRoleRef(role, r.get("np")));
×
583
                    }
×
584

585
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-pinned-templates", spaceIds), false).getData()) {
×
586
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
587
                        Template t = TemplateData.get().getTemplate(r.get("template"));
×
588
                        if (t == null) continue;
×
589
                        newData.pinnedResources.add(t);
×
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(TemplateData.get().getTemplate(r.get("template")));
×
594
                        }
595
                    }
×
596
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-pinned-queries", spaceIds), false).getData()) {
×
597
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
598
                        GrlcQuery query = GrlcQuery.get(r.get("query"));
×
599
                        if (query == null) continue;
×
600
                        newData.pinnedResources.add(query);
×
601
                        String tag = r.get("tag");
×
602
                        if (tag != null && !tag.isEmpty()) {
×
603
                            newData.pinGroupTags.add(r.get("tag"));
×
604
                            newData.pinnedResourceMap.computeIfAbsent(tag, k -> new HashSet<>()).add(query);
×
605
                        }
606
                    }
×
607
                    data = newData;
×
608
                    dataInitialized = true;
×
609
                } catch (Exception ex) {
×
610
                    logger.error("Error while trying to update space data: {}", ex);
×
611
                }
×
612
            });
×
613
            thread.start();
×
614
            dataNeedsUpdate = false;
×
615
            return thread;
×
616
        }
617
        return null;
×
618
    }
619

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

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