• 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

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

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

12
import org.eclipse.rdf4j.model.IRI;
13
import org.nanopub.Nanopub;
14
import org.nanopub.extra.services.ApiResponseEntry;
15
import org.nanopub.extra.services.QueryRef;
16
import org.slf4j.Logger;
17
import org.slf4j.LoggerFactory;
18

19
import com.knowledgepixels.nanodash.vocabulary.KPXL_TERMS;
20

21
public class ProfiledResource implements Serializable {
22

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

25
    protected static class ResourceData implements Serializable {
6✔
26
        List<ViewDisplay> viewDisplays = new ArrayList<>();
18✔
27
    }
28

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

31
    public static void refresh() {
32
        for (ProfiledResource r : instances.values()) {
11✔
33
            r.setDataNeedsUpdate();
2✔
34
        }
1✔
35
    }
1✔
36

37
    public static void forceRefresh(String id, long waitMillis) {
38
        if (isProfiledResource(id)) {
×
39
            instances.get(id).forceRefresh(waitMillis);
×
40
        }
41
    }
×
42

43
    public static boolean isProfiledResource(String id) {
44
        return instances.containsKey(id);
12✔
45
    }
46

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

54
    protected ProfiledResource(String id) {
6✔
55
        this.id = id;
9✔
56
        instances.put(id, this);
15✔
57
    }
3✔
58

59
    protected void initSpace(Space space) {
60
        this.space = space;
9✔
61
    }
3✔
62

63
    public String getId() {
64
        return id;
9✔
65
    }
66

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

78
                    ResourceData newData = new ResourceData();
×
79

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

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

108
    public Long getRunUpdateAfter() {
109
        return runUpdateAfter;
×
110
    }
111

112
    public Space getSpace() {
113
        return space;
×
114
    }
115

116
    public String getNanopubId() {
117
        return null;
×
118
    }
119

120
    public Nanopub getNanopub() {
121
        return null;
6✔
122
    }
123

124
    public String getNamespace() {
125
        return null;
×
126
    }
127

128
    public void setDataNeedsUpdate() {
129
        dataNeedsUpdate = true;
3✔
130
    }
1✔
131

132
    public boolean isDataInitialized() {
133
        triggerDataUpdate();
×
134
        return dataInitialized;
×
135
    }
136

137
    public List<ViewDisplay> getViewDisplays() {
138
        return data.viewDisplays;
×
139
    }
140

141
    public List<ViewDisplay> getTopLevelViewDisplays() {
142
        return getViewDisplays(true, getId(), null);
×
143
    }
144

145
    public List<ViewDisplay> getPartLevelViewDisplays(String resourceId, Set<IRI> classes) {
146
        return getViewDisplays(false, resourceId, classes);
×
147
    }
148

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

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

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

173
        Collections.sort(viewDisplays);
×
174
        return viewDisplays;
×
175
    }
176

177
    public String getLabel() {
178
        return space.getLabel();
×
179
    }
180

181
    @Override
182
    public String toString() {
183
        return id;
9✔
184
    }
185

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

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

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