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

knowledgepixels / nanodash / 17557135178

08 Sep 2025 04:12PM UTC coverage: 13.293% (+0.4%) from 12.856%
17557135178

push

github

ashleycaselli
test(NanopubElement): add unit tests

387 of 3854 branches covered (10.04%)

Branch coverage included in aggregate %.

1053 of 6979 relevant lines covered (15.09%)

0.67 hits per line

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

36.36
src/main/java/com/knowledgepixels/nanodash/NanopubElement.java
1
package com.knowledgepixels.nanodash;
2

3
import org.eclipse.rdf4j.model.IRI;
4
import org.eclipse.rdf4j.model.Statement;
5
import org.eclipse.rdf4j.model.vocabulary.RDF;
6
import org.nanopub.Nanopub;
7
import org.nanopub.NanopubUtils;
8
import org.nanopub.SimpleTimestampPattern;
9
import org.nanopub.extra.security.MalformedCryptoElementException;
10
import org.nanopub.extra.security.NanopubSignatureElement;
11
import org.nanopub.extra.security.SignatureUtils;
12
import org.slf4j.Logger;
13
import org.slf4j.LoggerFactory;
14

15
import java.io.Serializable;
16
import java.security.GeneralSecurityException;
17
import java.util.*;
18

19
/**
20
 * Represents a wrapper for a Nanopub object, providing additional metadata and utility methods.
21
 * This class includes caching mechanisms to avoid redundant Nanopub retrievals.
22
 */
23
public class NanopubElement implements Serializable {
24

25
    private static final long serialVersionUID = 1L;
26

27
    private static Map<String, NanopubElement> nanopubCache = new HashMap<>();
4✔
28
    private static final Logger logger = LoggerFactory.getLogger(NanopubElement.class);
4✔
29

30
    /**
31
     * Retrieves a NanopubElement instance for the given URI.
32
     * If the instance is not already cached, it creates a new one and caches it.
33
     *
34
     * @param uri The URI of the Nanopub.
35
     * @return The NanopubElement instance.
36
     */
37
    public static NanopubElement get(String uri) {
38
        if (!nanopubCache.containsKey(uri)) {
4!
39
            nanopubCache.put(uri, new NanopubElement(uri));
8✔
40
        }
41
        return nanopubCache.get(uri);
5✔
42
    }
43

44
    /**
45
     * Retrieves a NanopubElement instance for the given Nanopub object.
46
     * If the instance is not already cached, it creates a new one and caches it.
47
     *
48
     * @param nanopub The Nanopub object.
49
     * @return The NanopubElement instance.
50
     */
51
    public static NanopubElement get(Nanopub nanopub) {
52
        if (nanopub == null) {
2✔
53
            throw new IllegalArgumentException("Nanopub cannot be null");
5✔
54
        }
55
        String uri = nanopub.getUri().stringValue();
4✔
56
        if (!nanopubCache.containsKey(uri)) {
4✔
57
            nanopubCache.put(uri, new NanopubElement(nanopub));
8✔
58
        }
59
        return nanopubCache.get(uri);
5✔
60
    }
61

62
    private Nanopub nanopub;
63
    private String uriString; // Keeping URI separately, as nanopub might be null when it cannot be fetched
64
    private String label;
65
    private Calendar creationTime;
66
    private Boolean seemsToHaveSignature;
67
    private Boolean hasValidSignature;
68
    private IRI signerId;
69
    private List<IRI> types;
70
    private Map<String, String> foafNameMap;
71

72
    /**
73
     * Constructs a NanopubElement for the given URI.
74
     * Fetches the Nanopub object using the URI.
75
     *
76
     * @param uri The URI of the Nanopub.
77
     * @throws IllegalArgumentException If no Nanopub is found for the given URI.
78
     */
79
    private NanopubElement(String uri) {
2✔
80
        this.uriString = uri;
3✔
81
        this.nanopub = Utils.getNanopub(uri);
4✔
82
        if (nanopub == null) {
3!
83
            throw new IllegalArgumentException("No nanopublication found for URI: " + uri);
×
84
        }
85
    }
1✔
86

87
    /**
88
     * Constructs a NanopubElement for the given Nanopub object.
89
     *
90
     * @param nanopub The Nanopub object.
91
     */
92
    private NanopubElement(Nanopub nanopub) {
2✔
93
        this.uriString = nanopub.getUri().stringValue();
5✔
94
        this.nanopub = nanopub;
3✔
95
    }
1✔
96

97
    /**
98
     * Returns the Nanopub object.
99
     *
100
     * @return The Nanopub object.
101
     */
102
    public Nanopub getNanopub() {
103
        return nanopub;
3✔
104
    }
105

106
    /**
107
     * Returns the URI of the Nanopub.
108
     *
109
     * @return The URI as a string.
110
     */
111
    public String getUri() {
112
        return uriString;
3✔
113
    }
114

115
    /**
116
     * Returns the label of the Nanopub.
117
     * If the label is not already set, it retrieves it from the Nanopub.
118
     *
119
     * @return The label of the Nanopub.
120
     */
121
    public String getLabel() {
122
        if (label != null) return label;
6✔
123
        if (nanopub == null) return null;
3!
124
        label = NanopubUtils.getLabel(nanopub);
5✔
125
        if (label == null) label = "";
3!
126
        return label;
3✔
127
    }
128

129
    /**
130
     * Returns the creation time of the Nanopub.
131
     * If the creation time is not already set, it retrieves it using a timestamp pattern.
132
     *
133
     * @return The creation time as a Calendar object.
134
     */
135
    public Calendar getCreationTime() {
136
        if (nanopub == null) return null;
3!
137
        if (creationTime == null) {
3✔
138
            creationTime = SimpleTimestampPattern.getCreationTime(nanopub);
5✔
139
        }
140
        return creationTime;
3✔
141
    }
142

143
    /**
144
     * Checks if the Nanopub seems to have a signature.
145
     *
146
     * @return True if the Nanopub seems to have a signature, false otherwise.
147
     */
148
    public boolean seemsToHaveSignature() {
149
        if (nanopub == null) return false;
×
150
        if (seemsToHaveSignature == null) {
×
151
            seemsToHaveSignature = SignatureUtils.seemsToHaveSignature(nanopub);
×
152
        }
153
        return seemsToHaveSignature;
×
154
    }
155

156
    /**
157
     * Returns the public key of the Nanopub's signature.
158
     * If the signature is not valid, returns null.
159
     *
160
     * @return The public key as a string, or null if invalid.
161
     */
162
    public String getPubkey() {
163
        if (!hasValidSignature()) return null;
×
164
        try {
165
            return SignatureUtils.getSignatureElement(nanopub).getPublicKeyString();
×
166
        } catch (MalformedCryptoElementException ex) {
×
167
            logger.error("Error in getting the signature element of the nanopub {}", uriString, ex);
×
168
            return null;
×
169
        }
170
    }
171

172
    /**
173
     * Returns the SHA-256 hash of the public key of the Nanopub's signature
174
     *
175
     * @return The SHA-256 hash of the public key as a hexadecimal string, or null if the public key is not available.
176
     */
177
    public String getPubkeyhash() {
178
        String pubkey = getPubkey();
×
179
        if (pubkey == null) return null;
×
180
        return Utils.createSha256HexHash(pubkey);
×
181
    }
182

183
    /**
184
     * Checks if the Nanopub has a valid signature.
185
     *
186
     * @return True if the Nanopub has a valid signature, false otherwise.
187
     */
188
    public boolean hasValidSignature() {
189
        if (nanopub == null) return false;
×
190
        if (hasValidSignature == null) {
×
191
            try {
192
                NanopubSignatureElement se;
193
                se = SignatureUtils.getSignatureElement(nanopub);
×
194
                if (se != null) {
×
195
                    hasValidSignature = SignatureUtils.hasValidSignature(se);
×
196
                    if (se.getSigners().size() == 1) signerId = se.getSigners().iterator().next();
×
197
                } else {
198
                    hasValidSignature = false;
×
199
                }
200
            } catch (MalformedCryptoElementException | GeneralSecurityException ex) {
×
201
                logger.error("Error in checking the signature of the nanopub {}", uriString, ex);
×
202
                return false;
×
203
            }
×
204
        }
205
        return hasValidSignature;
×
206
    }
207

208
    /**
209
     * Returns the ID of the signer of the Nanopub.
210
     * If the signature is not valid, returns null.
211
     *
212
     * @return The signer ID as an IRI, or null if invalid.
213
     */
214
    public IRI getSignerId() {
215
        if (nanopub == null) return null;
×
216
        if (!hasValidSignature()) return null;
×
217
        return signerId;
×
218
    }
219

220
    /**
221
     * Returns the list of RDF types associated with the Nanopub.
222
     * If the types are not already set, it retrieves them from the Nanopub's pubinfo.
223
     *
224
     * @return A list of RDF types as IRIs.
225
     */
226
    public List<IRI> getTypes() {
227
        if (types == null) {
×
228
            types = new ArrayList<>();
×
229
            if (nanopub == null) return types;
×
230
            for (Statement st : nanopub.getPubinfo()) {
×
231
                if (st.getSubject().equals(nanopub.getUri()) && st.getPredicate().equals(RDF.TYPE) && st.getObject() instanceof IRI) {
×
232
                    types.add((IRI) st.getObject());
×
233
                }
234
            }
×
235
        }
236
        return types;
×
237
    }
238

239
    /**
240
     * Returns a map of FOAF names associated with the Nanopub.
241
     * If the map is not already set, it retrieves it using a utility method.
242
     *
243
     * @return A map of FOAF names.
244
     */
245
    public Map<String, String> getFoafNameMap() {
246
        if (foafNameMap == null) foafNameMap = Utils.getFoafNameMap(nanopub);
×
247
        return foafNameMap;
×
248
    }
249

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