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

knowledgepixels / nanodash / 21431284807

28 Jan 2026 08:43AM UTC coverage: 14.227% (-0.9%) from 15.111%
21431284807

push

github

tkuhn
feat: show label for profiled resources filled into form

548 of 5082 branches covered (10.78%)

Branch coverage included in aggregate %.

1500 of 9313 relevant lines covered (16.11%)

2.12 hits per line

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

31.9
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
            String id = getCoreInfoString(entry);
9✔
66
            Space space;
67
            if (prevSpacesByCoreInfoPrev.containsKey(id)) {
12!
68
                space = prevSpacesByCoreInfoPrev.get(id);
×
69
            } else {
70
                space = new Space(entry);
15✔
71
            }
72
            spaceList.add(space);
12✔
73
            spaceListByType.computeIfAbsent(space.getType(), k -> new ArrayList<>()).add(space);
39✔
74
            spacesByCoreInfo.put(space.getCoreInfoString(), space);
18✔
75
            spacesById.put(space.getId(), space);
18✔
76
        }
3✔
77
        for (Space space : spaceList) {
30✔
78
            Space superSpace = space.getIdSuperspace();
9✔
79
            if (superSpace == null) continue;
9✔
80
            subspaceMap.computeIfAbsent(superSpace, k -> new HashSet<>()).add(space);
36✔
81
            superspaceMap.computeIfAbsent(space, k -> new HashSet<>()).add(superSpace);
36✔
82
            space.setDataNeedsUpdate();
6✔
83
        }
3✔
84
        loaded = true;
6✔
85
    }
3✔
86

87
    /**
88
     * Check if the spaces have been loaded.
89
     *
90
     * @return true if loaded, false otherwise.
91
     */
92
    public static boolean isLoaded() {
93
        return loaded;
×
94
    }
95

96
    public static boolean areAllSpacesInitialized() {
97
        for (Space space : spaceList) {
×
98
            if (!space.isDataInitialized()) return false;
×
99
        }
×
100
        return true;
×
101
    }
102

103
    @Override
104
    public boolean isDataInitialized() {
105
        triggerDataUpdate();
×
106
        return dataInitialized && super.isDataInitialized();
×
107
    }
108

109
    public static void triggerAllDataUpdates() {
110
        for (Space space : spaceList) {
×
111
            space.triggerDataUpdate();
×
112
        }
×
113
    }
×
114

115
    private static final String ensureLoadedLock = "";
116

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

138
    public static void forceRootRefresh(long waitMillis) {
139
        spaceList = null;
×
140
        runRootUpdateAfter = System.currentTimeMillis() + waitMillis;
×
141
    }
×
142

143
    /**
144
     * Get the list of all spaces.
145
     *
146
     * @return List of spaces.
147
     */
148
    public static List<Space> getSpaceList() {
149
        ensureLoaded();
×
150
        return spaceList;
×
151
    }
152

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

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

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

186
    public void forceRefresh(long waitMillis) {
187
        super.forceRefresh(waitMillis);
×
188
        dataNeedsUpdate = true;
×
189
        dataInitialized = false;
×
190
    }
×
191

192
    private String label, rootNanopubId, type;
193
    private Nanopub rootNanopub = null;
9✔
194
    private SpaceData data = new SpaceData();
15✔
195

196
    private static class SpaceData implements Serializable {
6✔
197

198
        List<String> altIds = new ArrayList<>();
15✔
199

200
        String description = null;
9✔
201
        Calendar startDate, endDate;
202
        IRI defaultProvenance = null;
9✔
203

204
        List<IRI> admins = new ArrayList<>();
15✔
205
        Map<IRI, Set<SpaceMemberRoleRef>> users = new HashMap<>();
15✔
206
        List<SpaceMemberRoleRef> roles = new ArrayList<>();
15✔
207
        Map<IRI, SpaceMemberRole> roleMap = new HashMap<>();
15✔
208

209
        Map<String, IRI> adminPubkeyMap = new HashMap<>();
15✔
210
        Set<Serializable> pinnedResources = new HashSet<>();
15✔
211
        Set<String> pinGroupTags = new HashSet<>();
15✔
212
        Map<String, Set<Serializable>> pinnedResourceMap = new HashMap<>();
18✔
213

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

225
    }
226

227
    private static String getCoreInfoString(ApiResponseEntry resp) {
228
        String id = resp.get("space");
12✔
229
        String rootNanopubId = resp.get("np");
12✔
230
        return id + " " + rootNanopubId;
12✔
231
    }
232

233
    private boolean dataInitialized = false;
9✔
234
    private boolean dataNeedsUpdate = true;
9✔
235

236
    private Space(ApiResponseEntry resp) {
237
        super(resp.get("space"));
15✔
238
        initSpace(this);
9✔
239
        this.label = resp.get("label");
15✔
240
        this.type = resp.get("type");
15✔
241
        this.rootNanopubId = resp.get("np");
15✔
242
        this.rootNanopub = Utils.getAsNanopub(rootNanopubId);
15✔
243
        setCoreData(data);
12✔
244
    }
3✔
245

246
    /**
247
     * Get the root nanopublication ID of the space.
248
     *
249
     * @return The root nanopub ID.
250
     */
251
    @Override
252
    public String getNanopubId() {
253
        return rootNanopubId;
×
254
    }
255

256
    /**
257
     * Get a string combining the space ID and root nanopub ID for core identification.
258
     *
259
     * @return The core info string.
260
     */
261
    public String getCoreInfoString() {
262
        return getId() + " " + rootNanopubId;
18✔
263
    }
264

265
    /**
266
     * Get the root nanopublication of the space.
267
     *
268
     * @return The root Nanopub object.
269
     */
270
    @Override
271
    public Nanopub getNanopub() {
272
        return rootNanopub;
×
273
    }
274

275
    /**
276
     * Get the label of the space.
277
     *
278
     * @return The space label.
279
     */
280
    @Override
281
    public String getLabel() {
282
        return label;
×
283
    }
284

285
    /**
286
     * Get the type of the space.
287
     *
288
     * @return The space type.
289
     */
290
    public String getType() {
291
        return type;
9✔
292
    }
293

294
    /**
295
     * Get the start date of the space.
296
     *
297
     * @return The start date as a Calendar object, or null if not set.
298
     */
299
    public Calendar getStartDate() {
300
        return data.startDate;
×
301
    }
302

303
    /**
304
     * Get the end date of the space.
305
     *
306
     * @return The end date as a Calendar object, or null if not set.
307
     */
308
    public Calendar getEndDate() {
309
        return data.endDate;
×
310
    }
311

312
    /**
313
     * Get a simplified label for the type of space by removing any namespace prefix.
314
     *
315
     * @return The simplified type label.
316
     */
317
    public String getTypeLabel() {
318
        return type.replaceFirst("^.*/", "");
×
319
    }
320

321
    /**
322
     * Get the description of the space.
323
     *
324
     * @return The description string.
325
     */
326
    public String getDescription() {
327
        return data.description;
×
328
    }
329

330

331
    /**
332
     * Get the list of admins in this space.
333
     *
334
     * @return List of admin IRIs.
335
     */
336
    public List<IRI> getAdmins() {
337
        ensureInitialized();
×
338
        return data.admins;
×
339
    }
340

341
    /**
342
     * Get the list of members in this space.
343
     *
344
     * @return List of member IRIs.
345
     */
346
    public List<IRI> getUsers() {
347
        ensureInitialized();
×
348
        List<IRI> users = new ArrayList<IRI>(data.users.keySet());
×
349
        users.sort(User.getUserData().userComparator);
×
350
        return users;
×
351
    }
352

353
    /**
354
     * Get the roles of a specific member in this space.
355
     *
356
     * @param userId The IRI of the member.
357
     * @return Set of roles assigned to the member, or null if the member is not part of this space.
358
     */
359
    public Set<SpaceMemberRoleRef> getMemberRoles(IRI userId) {
360
        ensureInitialized();
×
361
        return data.users.get(userId);
×
362
    }
363

364
    /**
365
     * Check if a user is a member of this space.
366
     *
367
     * @param userId The IRI of the user to check.
368
     * @return true if the user is a member, false otherwise.
369
     */
370
    public boolean isMember(IRI userId) {
371
        ensureInitialized();
×
372
        return data.users.containsKey(userId);
×
373
    }
374

375
    public boolean isAdminPubkey(String pubkey) {
376
        ensureInitialized();
×
377
        return data.adminPubkeyMap.containsKey(pubkey);
×
378
    }
379

380
    /**
381
     * Get the list of pinned resources in this space.
382
     *
383
     * @return List of pinned resources.
384
     */
385
    public Set<Serializable> getPinnedResources() {
386
        ensureInitialized();
×
387
        return data.pinnedResources;
×
388
    }
389

390
    /**
391
     * Get the set of tags used for grouping pinned resources.
392
     *
393
     * @return Set of tags.
394
     */
395
    public Set<String> getPinGroupTags() {
396
        ensureInitialized();
×
397
        return data.pinGroupTags;
×
398
    }
399

400
    /**
401
     * Get a map of pinned resources grouped by their tags.
402
     *
403
     * @return Map where keys are tags and values are lists of pinned resources (Templates or GrlcQueries).
404
     */
405
    public Map<String, Set<Serializable>> getPinnedResourceMap() {
406
        ensureInitialized();
×
407
        return data.pinnedResourceMap;
×
408
    }
409

410
    public boolean appliesTo(String elementId, Set<IRI> classes) {
411
        triggerDataUpdate();
×
412
        for (ViewDisplay v : getViewDisplays()) {
×
413
            if (v.appliesTo(elementId, classes)) return true;
×
414
        }
×
415
        return false;
×
416
    }
417

418
    /**
419
     * Get the default provenance IRI for this space.
420
     *
421
     * @return The default provenance IRI, or null if not set.
422
     */
423
    public IRI getDefaultProvenance() {
424
        return data.defaultProvenance;
×
425
    }
426

427
    /**
428
     * Get the roles defined in this space.
429
     *
430
     * @return List of roles.
431
     */
432
    public List<SpaceMemberRoleRef> getRoles() {
433
        return data.roles;
×
434
    }
435

436
    /**
437
     * Get the super ID of the space.
438
     *
439
     * @return Always returns null. Use getIdSuperspace() instead.
440
     */
441
    public String getSuperId() {
442
        return null;
×
443
    }
444

445
    /**
446
     * Get the superspace ID.
447
     *
448
     * @return The superspace, or null if not applicable.
449
     */
450
    public Space getIdSuperspace() {
451
        if (!getId().matches("https?://[^/]+/.*/[^/]*/?")) return null;
15!
452
        String superId = getId().replaceFirst("(https?://[^/]+/.*)/[^/]*/?", "$1");
18✔
453
        if (spacesById.containsKey(superId)) {
12✔
454
            return spacesById.get(superId);
15✔
455
        }
456
        return null;
6✔
457
    }
458

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

473
    /**
474
     * Get subspaces of this space.
475
     *
476
     * @return List of subspaces.
477
     */
478
    public List<Space> getSubspaces() {
479
        if (subspaceMap.containsKey(this)) {
×
480
            List<Space> subspaces = new ArrayList<>(subspaceMap.get(this));
×
481
            Collections.sort(subspaces, Ordering.usingToString());
×
482
            return subspaces;
×
483
        }
484
        return new ArrayList<>();
×
485
    }
486

487
    /**
488
     * Get subspaces of a specific type.
489
     *
490
     * @param type The type of subspaces to retrieve.
491
     * @return List of subspaces of the specified type.
492
     */
493
    public List<Space> getSubspaces(String type) {
494
        List<Space> l = new ArrayList<>();
×
495
        for (Space s : getSubspaces()) {
×
496
            if (s.getType().equals(type)) l.add(s);
×
497
        }
×
498
        return l;
×
499
    }
500

501
    /**
502
     * Get alternative IDs for the space.
503
     *
504
     * @return List of alternative IDs.
505
     */
506
    public List<String> getAltIDs() {
507
        return data.altIds;
×
508
    }
509

510
    private synchronized void ensureInitialized() {
511
        Thread thread = triggerSpaceDataUpdate();
×
512
        if (!dataInitialized && thread != null) {
×
513
            try {
514
                thread.join();
×
515
            } catch (InterruptedException ex) {
×
516
                logger.error("failed to join thread", ex);
×
517
            }
×
518
        }
519
        thread = super.triggerDataUpdate();
×
520
        if (!dataInitialized && thread != null) {
×
521
            try {
522
                thread.join();
×
523
            } catch (InterruptedException ex) {
×
524
                logger.error("failed to join thread", ex);
×
525
            }
×
526
        }
527
    }
×
528

529
    @Override
530
    public synchronized Thread triggerDataUpdate() {
531
        triggerSpaceDataUpdate();
×
532
        return super.triggerDataUpdate();
×
533
    }
534

535
    private synchronized Thread triggerSpaceDataUpdate() {
536
        if (dataNeedsUpdate) {
×
537
            Thread thread = new Thread(() -> {
×
538
                try {
539
                    if (getRunUpdateAfter() != null) {
×
540
                        while (System.currentTimeMillis() < getRunUpdateAfter()) {
×
541
                            Thread.sleep(100);
×
542
                        }
543
                    }
544
                    SpaceData newData = new SpaceData();
×
545
                    setCoreData(newData);
×
546

547
                    newData.roles.add(new SpaceMemberRoleRef(SpaceMemberRole.ADMIN_ROLE, null));
×
548
                    newData.roleMap.put(KPXL_TERMS.HAS_ADMIN_PREDICATE, SpaceMemberRole.ADMIN_ROLE);
×
549

550
                    // TODO Improve this:
551
                    Multimap<String, String> spaceIds = ArrayListMultimap.create();
×
552
                    Multimap<String, String> resourceIds = ArrayListMultimap.create();
×
553
                    spaceIds.put("space", getId());
×
554
                    resourceIds.put("resource", getId());
×
555
                    for (String id : newData.altIds) {
×
556
                        spaceIds.put("space", id);
×
557
                        resourceIds.put("resource", id);
×
558
                    }
×
559

560
                    ApiResponse getAdminsResponse = ApiCache.retrieveResponseSync(new QueryRef("get-admins", spaceIds), false);
×
561
                    boolean continueAddingAdmins = true;
×
562
                    while (continueAddingAdmins) {
×
563
                        continueAddingAdmins = false;
×
564
                        for (ApiResponseEntry r : getAdminsResponse.getData()) {
×
565
                            String pubkeyhash = r.get("pubkey");
×
566
                            if (newData.adminPubkeyMap.containsKey(pubkeyhash)) {
×
567
                                IRI adminId = Utils.vf.createIRI(r.get("admin"));
×
568
                                if (!newData.admins.contains(adminId)) {
×
569
                                    continueAddingAdmins = true;
×
570
                                    newData.addAdmin(adminId, r.get("np"));
×
571
                                }
572
                            }
573
                        }
×
574
                    }
575
                    newData.admins.sort(User.getUserData().userComparator);
×
576

577
                    Multimap<String, String> getSpaceMemberParams = ArrayListMultimap.create(spaceIds);
×
578

579
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-space-member-roles", spaceIds), false).getData()) {
×
580
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
581
                        SpaceMemberRole role = new SpaceMemberRole(r);
×
582
                        newData.roles.add(new SpaceMemberRoleRef(role, r.get("np")));
×
583

584
                        // TODO Handle cases of overlapping properties:
585
                        for (IRI p : role.getRegularProperties()) newData.roleMap.put(p, role);
×
586
                        for (IRI p : role.getInverseProperties()) newData.roleMap.put(p, role);
×
587

588
                        role.addRoleParams(getSpaceMemberParams);
×
589
                    }
×
590

591
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-space-members", getSpaceMemberParams), false).getData()) {
×
592
                        IRI memberId = Utils.vf.createIRI(r.get("member"));
×
593
                        SpaceMemberRole role = newData.roleMap.get(Utils.vf.createIRI(r.get("role")));
×
594
                        newData.users.computeIfAbsent(memberId, (k) -> new HashSet<>()).add(new SpaceMemberRoleRef(role, r.get("np")));
×
595
                    }
×
596

597
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-pinned-templates", spaceIds), false).getData()) {
×
598
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
599
                        Template t = TemplateData.get().getTemplate(r.get("template"));
×
600
                        if (t == null) continue;
×
601
                        newData.pinnedResources.add(t);
×
602
                        String tag = r.get("tag");
×
603
                        if (tag != null && !tag.isEmpty()) {
×
604
                            newData.pinGroupTags.add(r.get("tag"));
×
605
                            newData.pinnedResourceMap.computeIfAbsent(tag, k -> new HashSet<>()).add(TemplateData.get().getTemplate(r.get("template")));
×
606
                        }
607
                    }
×
608
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-pinned-queries", spaceIds), false).getData()) {
×
609
                        if (!newData.adminPubkeyMap.containsKey(r.get("pubkey"))) continue;
×
610
                        GrlcQuery query = GrlcQuery.get(r.get("query"));
×
611
                        if (query == null) continue;
×
612
                        newData.pinnedResources.add(query);
×
613
                        String tag = r.get("tag");
×
614
                        if (tag != null && !tag.isEmpty()) {
×
615
                            newData.pinGroupTags.add(r.get("tag"));
×
616
                            newData.pinnedResourceMap.computeIfAbsent(tag, k -> new HashSet<>()).add(query);
×
617
                        }
618
                    }
×
619
                    data = newData;
×
620
                    dataInitialized = true;
×
621
                } catch (Exception ex) {
×
622
                    logger.error("Error while trying to update space data: {}", ex);
×
623
                }
×
624
            });
×
625
            thread.start();
×
626
            dataNeedsUpdate = false;
×
627
            return thread;
×
628
        }
629
        return null;
×
630
    }
631

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

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