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

knowledgepixels / nanodash / 17380144000

01 Sep 2025 02:12PM UTC coverage: 12.03% (+0.05%) from 11.978%
17380144000

push

github

ashleycaselli
refactor: replace printStackTrace with logger.error for better error handling

330 of 3850 branches covered (8.57%)

Branch coverage included in aggregate %.

958 of 6857 relevant lines covered (13.97%)

0.62 hits per line

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

9.48
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)) {
×
39
            nanopubCache.put(uri, new NanopubElement(uri));
×
40
        }
41
        return nanopubCache.get(uri);
×
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
        String uri = nanopub.getUri().stringValue();
4✔
53
        if (!nanopubCache.containsKey(uri)) {
4!
54
            nanopubCache.put(uri, new NanopubElement(nanopub));
8✔
55
        }
56
        return nanopubCache.get(uri);
5✔
57
    }
58

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

69

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

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

93
    /**
94
     * Returns the Nanopub object.
95
     *
96
     * @return The Nanopub object.
97
     */
98
    public Nanopub getNanopub() {
99
        return nanopub;
×
100
    }
101

102
    /**
103
     * Returns the URI of the Nanopub.
104
     *
105
     * @return The URI as a string.
106
     */
107
    public String getUri() {
108
        return uriString;
×
109
    }
110

111
    /**
112
     * Returns the label of the Nanopub.
113
     * If the label is not already set, it retrieves it from the Nanopub.
114
     *
115
     * @return The label of the Nanopub.
116
     */
117
    public String getLabel() {
118
        if (label != null) return label;
×
119
        if (nanopub == null) return null;
×
120
        label = NanopubUtils.getLabel(nanopub);
×
121
        if (label == null) label = "";
×
122
        return label;
×
123
    }
124

125
    /**
126
     * Returns the creation time of the Nanopub.
127
     * If the creation time is not already set, it retrieves it using a timestamp pattern.
128
     *
129
     * @return The creation time as a Calendar object.
130
     */
131
    public Calendar getCreationTime() {
132
        if (nanopub == null) return null;
×
133
        if (creationTime == null) {
×
134
            creationTime = SimpleTimestampPattern.getCreationTime(nanopub);
×
135
        }
136
        return creationTime;
×
137
    }
138

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

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

168
    public String getPubkeyhash() {
169
        String pubkey = getPubkey();
×
170
        if (pubkey == null) return null;
×
171
        return Utils.createSha256HexHash(pubkey);
×
172
    }
173

174
    /**
175
     * Checks if the Nanopub has a valid signature.
176
     *
177
     * @return True if the Nanopub has a valid signature, false otherwise.
178
     */
179
    public boolean hasValidSignature() {
180
        if (nanopub == null) return false;
×
181
        if (hasValidSignature == null) {
×
182
            try {
183
                NanopubSignatureElement se;
184
                se = SignatureUtils.getSignatureElement(nanopub);
×
185
                if (se != null) {
×
186
                    hasValidSignature = SignatureUtils.hasValidSignature(se);
×
187
                    if (se.getSigners().size() == 1) signerId = se.getSigners().iterator().next();
×
188
                } else {
189
                    hasValidSignature = false;
×
190
                }
191
            } catch (MalformedCryptoElementException | GeneralSecurityException ex) {
×
192
                logger.error("Error in checking the signature of the nanopub {}", uriString, ex);
×
193
                return false;
×
194
            }
×
195
        }
196
        return hasValidSignature;
×
197
    }
198

199
    /**
200
     * Returns the ID of the signer of the Nanopub.
201
     * If the signature is not valid, returns null.
202
     *
203
     * @return The signer ID as an IRI, or null if invalid.
204
     */
205
    public IRI getSignerId() {
206
        if (nanopub == null) return null;
×
207
        if (!hasValidSignature()) return null;
×
208
        return signerId;
×
209
    }
210

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

230
    /**
231
     * Returns a map of FOAF names associated with the Nanopub.
232
     * If the map is not already set, it retrieves it using a utility method.
233
     *
234
     * @return A map of FOAF names.
235
     */
236
    public Map<String, String> getFoafNameMap() {
237
        if (foafNameMap == null) foafNameMap = Utils.getFoafNameMap(nanopub);
×
238
        return foafNameMap;
×
239
    }
240

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