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

knowledgepixels / nanodash / 20990415403

14 Jan 2026 10:13AM UTC coverage: 14.11% (-1.1%) from 15.173%
20990415403

push

github

tkuhn
fix(AjaxZonedDateTimePicker): Avoid NullPointerException when optional

540 of 5062 branches covered (10.67%)

Branch coverage included in aggregate %.

1484 of 9282 relevant lines covered (15.99%)

2.81 hits per line

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

50.0
src/main/java/com/knowledgepixels/nanodash/MaintainedResource.java
1
package com.knowledgepixels.nanodash;
2

3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.Set;
8

9
import org.eclipse.rdf4j.model.IRI;
10
import org.nanopub.Nanopub;
11
import org.nanopub.extra.services.ApiResponse;
12
import org.nanopub.extra.services.ApiResponseEntry;
13
import org.nanopub.extra.services.QueryRef;
14
import org.slf4j.Logger;
15
import org.slf4j.LoggerFactory;
16

17
public class MaintainedResource extends ProfiledResource {
18

19
    private static final Logger logger = LoggerFactory.getLogger(MaintainedResource.class);
12✔
20

21
    private static List<MaintainedResource> resourceList;
22
    private static Map<String, MaintainedResource> resourcesById;
23
    private static Map<String, MaintainedResource> resourcesByNamespace;
24
    private static Map<Space, List<MaintainedResource>> resourcesBySpace;
25
    private static boolean loaded = false;
8✔
26
    private static Long runRootUpdateAfter = null;
12✔
27

28
    public static synchronized void refresh(ApiResponse resp) {
29
        resourceList = new ArrayList<>();
16✔
30
        Map<String, MaintainedResource> previousResourcesById = resourcesById;
8✔
31
        resourcesById = new HashMap<>();
16✔
32
        resourcesBySpace = new HashMap<>();
16✔
33
        resourcesByNamespace = new HashMap<>();
16✔
34
        for (ApiResponseEntry entry : resp.getData()) {
44!
35
            Space space = Space.get(entry.get("space"));
20✔
36
            if (space == null) continue;
8!
37
            MaintainedResource resource = null;
8✔
38
            if (previousResourcesById != null) {
8!
39
                resource = previousResourcesById.get(entry.get("resource"));
×
40
            }
41
            if (resource == null) {
8!
42
                resource = new MaintainedResource(entry, space);
24✔
43
            }
44
            if (resourcesById.containsKey(resource.getId())) continue;
24✔
45
            resourceList.add(resource);
16✔
46
            resourcesById.put(resource.getId(), resource);
24✔
47
            resourcesBySpace.computeIfAbsent(space, k -> new ArrayList<>()).add(resource);
48✔
48
            if (resource.getNamespace() != null) {
12✔
49
                // TODO Handle conflicts when two resources claim the same namespace:
50
                resourcesByNamespace.put(resource.getNamespace(), resource);
24✔
51
            }
52
        }
4✔
53
        loaded = true;
×
54
    }
×
55

56
    /**
57
     * Check if the resources have been loaded.
58
     *
59
     * @return true if loaded, false otherwise.
60
     */
61
    public static boolean isLoaded() {
62
        return loaded;
×
63
    }
64

65
    /**
66
     * Ensure that the resources are loaded, fetching them from the API if necessary.
67
     */
68
    public static void ensureLoaded() {
69
        if (resourceList == null) {
8!
70
            try {
71
                if (runRootUpdateAfter != null) {
×
72
                    while (System.currentTimeMillis() < runRootUpdateAfter) {
×
73
                        Thread.sleep(100);
×
74
                    }
75
                    runRootUpdateAfter = null;
×
76
                }
77
            } catch (InterruptedException ex) {
×
78
                logger.error("Interrupted", ex);
×
79
            }
×
80
            refresh(ApiCache.retrieveResponseSync(new QueryRef("get-maintained-resources"), true));
×
81
        }
82
    }
4✔
83

84
    public static void forceRootRefresh(long waitMillis) {
85
        resourceList = null;
×
86
        runRootUpdateAfter = System.currentTimeMillis() + waitMillis;
×
87
    }
×
88

89
    /**
90
     * Get the list of all maintained resources.
91
     *
92
     * @return List of resources.
93
     */
94
    public static List<MaintainedResource> getResourceList() {
95
        ensureLoaded();
×
96
        return resourceList;
×
97
    }
98

99
    public static List<MaintainedResource> getResourcesBySpace(Space space) {
100
        return resourcesBySpace.computeIfAbsent(space, k -> new ArrayList<>());
×
101
    }
102

103
    /**
104
     * Get a maintained resource by its id.
105
     *
106
     * @param id The id of the resource.
107
     * @return The corresponding MaintainedResource object, or null if not found.
108
     */
109
    public static MaintainedResource get(String id) {
110
        ensureLoaded();
4✔
111
        return resourcesById.get(id);
20✔
112
    }
113

114
    public static MaintainedResource getByNamespace(String namespace) {
115
        return resourcesByNamespace.get(namespace);
×
116
    }
117

118
    public static String getNamespace(Object stringOrIri) {
119
        return stringOrIri.toString().replaceFirst("([#/])[^#/]+$", "$1");
×
120
    }
121

122
    public static void refresh() {
123
        refresh(ApiCache.retrieveResponseSync(new QueryRef("get-maintained-resources"), true));
×
124
        for (MaintainedResource resource : resourceList) {
×
125
            resource.setDataNeedsUpdate();
×
126
        }
×
127
    }
×
128

129
    private String label, nanopubId, namespace;
130
    private Nanopub nanopub;
131

132
    private MaintainedResource(ApiResponseEntry resp, Space space) {
133
        super(resp.get("resource"));
20✔
134
        initialize(resp, space);
16✔
135
    }
4✔
136

137
    private void initialize(ApiResponseEntry resp, Space space) {
138
        initSpace(space);
12✔
139
        this.label = resp.get("label");
20✔
140
        this.nanopubId = resp.get("np");
20✔
141
        this.namespace = resp.get("namespace");
20✔
142
        if (namespace != null && namespace.isBlank()) namespace = null;
40!
143
        this.nanopub = Utils.getAsNanopub(nanopubId);
20✔
144
    }
4✔
145

146
    @Override
147
    public String getNanopubId() {
148
        return nanopubId;
×
149
    }
150

151
    @Override
152
    public Nanopub getNanopub() {
153
        return nanopub;
×
154
    }
155

156
    public String getLabel() {
157
        return label;
×
158
    }
159

160
    @Override
161
    public String getNamespace() {
162
        return namespace;
12✔
163
    }
164

165
    public boolean appliesTo(String elementId, Set<IRI> classes) {
166
        triggerDataUpdate();
×
167
        for (ViewDisplay v : getViewDisplays()) {
×
168
            if (v.appliesTo(elementId, classes)) return true;
×
169
        }
×
170
        return false;
×
171
    }
172

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