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

knowledgepixels / nanodash / 21595339141

02 Feb 2026 03:05PM UTC coverage: 13.882% (+0.1%) from 13.774%
21595339141

Pull #348

github

web-flow
Merge 65237e603 into 749c79335
Pull Request #348: Implement Nanopubs list/grid as `ResourceView`

551 of 5258 branches covered (10.48%)

Branch coverage included in aggregate %.

1510 of 9589 relevant lines covered (15.75%)

2.06 hits per line

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

14.84
src/main/java/com/knowledgepixels/nanodash/ProfiledResource.java
1
package com.knowledgepixels.nanodash;
2

3
import com.knowledgepixels.nanodash.vocabulary.KPXL_TERMS;
4
import org.eclipse.rdf4j.model.IRI;
5
import org.nanopub.Nanopub;
6
import org.nanopub.extra.services.ApiResponseEntry;
7
import org.nanopub.extra.services.QueryRef;
8
import org.slf4j.Logger;
9
import org.slf4j.LoggerFactory;
10

11
import java.io.Serializable;
12
import java.util.*;
13

14
public abstract class ProfiledResource implements Serializable {
15

16
    private static final Logger logger = LoggerFactory.getLogger(ProfiledResource.class);
9✔
17

18
    protected static class ResourceData implements Serializable {
6✔
19
        List<ViewDisplay> viewDisplays = new ArrayList<>();
18✔
20
    }
21

22
    private static Map<String, ProfiledResource> instances = new HashMap<>();
15✔
23

24
    public static void refresh() {
25
        for (ProfiledResource r : instances.values()) {
11✔
26
            r.setDataNeedsUpdate();
2✔
27
        }
1✔
28
    }
1✔
29

30
    public static void forceRefresh(String id, long waitMillis) {
31
        if (isProfiledResource(id)) {
×
32
            instances.get(id).forceRefresh(waitMillis);
×
33
        }
34
    }
×
35

36
    public static boolean isProfiledResource(String id) {
37
        return instances.containsKey(id);
×
38
    }
39

40
    public static ProfiledResource get(String id) {
41
        return instances.get(id);
×
42
    }
43

44
    private String id;
45
    private Space space;
46
    private ResourceData data = new ResourceData();
15✔
47
    private boolean dataInitialized = false;
9✔
48
    private boolean dataNeedsUpdate = true;
9✔
49
    private Long runUpdateAfter = null;
9✔
50

51
    protected ProfiledResource(String id) {
6✔
52
        this.id = id;
9✔
53
        instances.put(id, this);
15✔
54
    }
3✔
55

56
    protected void initSpace(Space space) {
57
        this.space = space;
9✔
58
    }
3✔
59

60
    public String getId() {
61
        return id;
9✔
62
    }
63

64
    public synchronized Thread triggerDataUpdate() {
65
        if (dataNeedsUpdate) {
×
66
            Thread thread = new Thread(() -> {
×
67
                try {
68
                    if (runUpdateAfter != null) {
×
69
                        while (System.currentTimeMillis() < runUpdateAfter) {
×
70
                            Thread.sleep(100);
×
71
                        }
72
                        runUpdateAfter = null;
×
73
                    }
74

75
                    ResourceData newData = new ResourceData();
×
76

77
                    for (ApiResponseEntry r : ApiCache.retrieveResponseSync(new QueryRef("get-view-displays", "resource", id), true).getData()) {
×
78
                        if (space != null && !space.isAdminPubkey(r.get("pubkey"))) continue;
×
79
                        try {
80
                            newData.viewDisplays.add(ViewDisplay.get(r.get("display")));
×
81
                        } catch (IllegalArgumentException ex) {
×
82
                            logger.error("Couldn't generate view display object", ex);
×
83
                        }
×
84
                    }
×
85
                    data = newData;
×
86
                    dataInitialized = true;
×
87
                } catch (Exception ex) {
×
88
                    logger.error("Error while trying to update space data: {}", ex);
×
89
                    dataNeedsUpdate = true;
×
90
                }
×
91
            });
×
92
            thread.start();
×
93
            dataNeedsUpdate = false;
×
94
            return thread;
×
95
        }
96
        return null;
×
97
    }
98

99
    public void forceRefresh(long waitMillis) {
100
        dataNeedsUpdate = true;
×
101
        dataInitialized = false;
×
102
        runUpdateAfter = System.currentTimeMillis() + waitMillis;
×
103
    }
×
104

105
    public Long getRunUpdateAfter() {
106
        return runUpdateAfter;
×
107
    }
108

109
    public Space getSpace() {
110
        return space;
×
111
    }
112

113
    public String getNanopubId() {
114
        return null;
×
115
    }
116

117
    public Nanopub getNanopub() {
118
        return null;
×
119
    }
120

121
    public String getNamespace() {
122
        return null;
×
123
    }
124

125
    public void setDataNeedsUpdate() {
126
        dataNeedsUpdate = true;
9✔
127
    }
3✔
128

129
    public boolean isDataInitialized() {
130
        triggerDataUpdate();
×
131
        return dataInitialized;
×
132
    }
133

134
    public List<ViewDisplay> getViewDisplays() {
135
        return data.viewDisplays;
×
136
    }
137

138
    public List<ViewDisplay> getTopLevelViewDisplays() {
139
        return getViewDisplays(true, getId(), null);
×
140
    }
141

142
    public List<ViewDisplay> getPartLevelViewDisplays(String resourceId, Set<IRI> classes) {
143
        return getViewDisplays(false, resourceId, classes);
×
144
    }
145

146
    private List<ViewDisplay> getViewDisplays(boolean toplevel, String resourceId, Set<IRI> classes) {
147
        triggerDataUpdate();
×
148
        List<ViewDisplay> viewDisplays = new ArrayList<>();
×
149
        Set<IRI> viewKinds = new HashSet<>();
×
150

151
        for (ViewDisplay vd : getViewDisplays()) {
×
152
            IRI kind = vd.getViewKindIri();
×
153
            if (kind != null) {
×
154
                if (viewKinds.contains(kind)) {
×
155
                    continue;
×
156
                }
157
                viewKinds.add(vd.getViewKindIri());
×
158
            }
159
            if (vd.hasType(KPXL_TERMS.DEACTIVATED_VIEW_DISPLAY)) {
×
160
                continue;
×
161
            }
162

163
            if (!toplevel && vd.hasType(KPXL_TERMS.TOP_LEVEL_VIEW_DISPLAY)) {
×
164
                // Deprecated
165
                // do nothing
166
            } else if (vd.appliesTo(resourceId, classes)) {
×
167
                viewDisplays.add(vd);
×
168
            } else if (toplevel && vd.hasType(KPXL_TERMS.TOP_LEVEL_VIEW_DISPLAY)) {
×
169
                // Deprecated
170
                viewDisplays.add(vd);
×
171
            }
172
        }
×
173

174
        // This is a temporary hack to always show the latest nanopubs view for users by default without needing to create a ViewDisplay for each user
175
        // TODO remove this once we have a better system for default views
176
        if (User.isUser(resourceId)) {
×
177
            ViewDisplay latestNpsViewDisplay = new ViewDisplay(ResourceView.get("https://w3id.org/np/RAjYa33Z3H1whRl486AW3LMnV11WQqkTqvuHROhKbmtlE/latest-nanopubs-example"));
×
178
            viewDisplays.add(latestNpsViewDisplay);
×
179
        }
180

181
        Collections.sort(viewDisplays);
×
182
        return viewDisplays;
×
183
    }
184

185
    public abstract String getLabel();
186

187
    @Override
188
    public String toString() {
189
        return id;
×
190
    }
191

192
    /**
193
     * Gets the chain of superspaces from the current space up to the root space.
194
     *
195
     * @return the list of superspaces from the given space to the root space
196
     */
197
    public List<ProfiledResource> getAllSuperSpacesUntilRoot() {
198
        List<ProfiledResource> chain = new ArrayList<>();
×
199
        Set<String> visited = new HashSet<>();
×
200
        collectAncestors(space, chain, visited);
×
201
        Collections.reverse(chain);
×
202
        return chain;
×
203
    }
204

205
    private void collectAncestors(Space current, List<ProfiledResource> chain, Set<String> visited) {
206
        if (current == null) {
×
207
            return;
×
208
        }
209
        List<Space> parents = current.getSuperspaces();
×
210
        if (parents == null || parents.isEmpty()) {
×
211
            return;
×
212
        }
213
        Space parent = parents.getFirst();
×
214
        if (parent == null) {
×
215
            return;
×
216
        }
217
        String pid = parent.getId();
×
218
        if (pid == null || !visited.add(pid)) {
×
219
            return;
×
220
        }
221
        chain.add(parent);
×
222
        collectAncestors(parent, chain, visited);
×
223
    }
×
224

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