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

knowledgepixels / nanodash / 17264559856

27 Aug 2025 10:47AM UTC coverage: 12.401% (-0.002%) from 12.403%
17264559856

push

github

tkuhn
Create separate Utils methods for (un)escaping literal strings

332 of 3818 branches covered (8.7%)

Branch coverage included in aggregate %.

989 of 6834 relevant lines covered (14.47%)

0.64 hits per line

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

57.62
src/main/java/com/knowledgepixels/nanodash/Utils.java
1
package com.knowledgepixels.nanodash;
2

3
import com.google.common.hash.Hashing;
4
import net.trustyuri.TrustyUriUtils;
5
import org.apache.commons.codec.Charsets;
6
import org.apache.commons.exec.environment.EnvironmentUtils;
7
import org.apache.commons.lang.StringUtils;
8
import org.apache.http.client.utils.URIBuilder;
9
import org.apache.wicket.markup.html.link.ExternalLink;
10
import org.apache.wicket.model.IModel;
11
import org.apache.wicket.request.mapper.parameter.PageParameters;
12
import org.apache.wicket.util.string.StringValue;
13
import org.eclipse.rdf4j.model.IRI;
14
import org.eclipse.rdf4j.model.Literal;
15
import org.eclipse.rdf4j.model.Statement;
16
import org.eclipse.rdf4j.model.ValueFactory;
17
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
18
import org.eclipse.rdf4j.model.vocabulary.FOAF;
19
import org.nanopub.Nanopub;
20
import org.nanopub.NanopubUtils;
21
import org.nanopub.extra.security.KeyDeclaration;
22
import org.nanopub.extra.security.MalformedCryptoElementException;
23
import org.nanopub.extra.security.NanopubSignatureElement;
24
import org.nanopub.extra.security.SignatureUtils;
25
import org.nanopub.extra.server.GetNanopub;
26
import org.nanopub.extra.services.ApiResponseEntry;
27
import org.nanopub.extra.setting.IntroNanopub;
28
import org.owasp.html.HtmlPolicyBuilder;
29
import org.owasp.html.PolicyFactory;
30
import org.wicketstuff.select2.Select2Choice;
31

32
import java.io.IOException;
33
import java.io.Serializable;
34
import java.net.URISyntaxException;
35
import java.net.URLDecoder;
36
import java.net.URLEncoder;
37
import java.nio.charset.StandardCharsets;
38
import java.util.*;
39

40
/**
41
 * Utility class providing various helper methods for handling nanopublications, URIs, and other related functionalities.
42
 */
43
public class Utils {
44

45
    private Utils() {
46
    }  // no instances allowed
47

48
    public static final ValueFactory vf = SimpleValueFactory.getInstance();
2✔
49

50
    // TODO Merge with IriItem.getShortNameFromURI
51
    public static String getShortNameFromURI(IRI uri) {
52
        return getShortNameFromURI(uri.stringValue());
4✔
53
    }
54

55
    public static String getShortNameFromURI(String u) {
56
        u = u.replaceFirst("\\?.*$", "");
5✔
57
        u = u.replaceFirst("[/#]$", "");
5✔
58
        u = u.replaceFirst("^.*[/#]([^/#]*)[/#]([0-9]+)$", "$1/$2");
5✔
59
        u = u.replaceFirst("^.*[/#]([^/#]*[^0-9][^/#]*)$", "$1");
5✔
60
        u = u.replaceFirst("((^|[^A-Za-z0-9\\-_])RA[A-Za-z0-9\\-_]{8})[A-Za-z0-9\\-_]{35}$", "$1");
5✔
61
        u = u.replaceFirst("(^|[^A-Za-z0-9\\-_])RA[A-Za-z0-9\\-_]{43}[^A-Za-z0-9\\-_](.+)$", "$2");
5✔
62
        return u;
2✔
63
    }
64

65
    public static String getShortNanopubId(Object npId) {
66
        return TrustyUriUtils.getArtifactCode(npId.toString()).substring(0, 10);
7✔
67
    }
68

69
    private static Map<String, Nanopub> nanopubs = new HashMap<>();
4✔
70

71
    public static Nanopub getNanopub(String uriOrArtifactCode) {
72
        String artifactCode = getArtifactCode(uriOrArtifactCode);
3✔
73
        if (!nanopubs.containsKey(artifactCode)) {
4✔
74
            for (int i = 0; i < 3; i++) {  // Try 3 times to get nanopub
5!
75
                Nanopub np = GetNanopub.get(artifactCode);
3✔
76
                if (np != null) {
2!
77
                    nanopubs.put(artifactCode, np);
5✔
78
                    break;
1✔
79
                }
80
            }
81
        }
82
        return nanopubs.get(artifactCode);
5✔
83
    }
84

85
    public static String getArtifactCode(String uriOrArtifactCode) {
86
        return uriOrArtifactCode.replaceFirst("^.*(RA[0-9a-zA-Z\\-_]{43})(\\?.*)?$", "$1");
5✔
87
    }
88

89
    public static String urlEncode(Object o) {
90
        return URLEncoder.encode((o == null ? "" : o.toString()), Charsets.UTF_8);
9✔
91
    }
92

93
    public static String urlDecode(Object o) {
94
        return URLDecoder.decode((o == null ? "" : o.toString()), Charsets.UTF_8);
9✔
95
    }
96

97
    public static String getUrlWithParameters(String base, PageParameters parameters) {
98
        try {
99
            URIBuilder u = new URIBuilder(base);
5✔
100
            for (String key : parameters.getNamedKeys()) {
11✔
101
                for (StringValue value : parameters.getValues(key)) {
12✔
102
                    if (!value.isNull()) u.addParameter(key, value.toString());
9!
103
                }
1✔
104
            }
1✔
105
            return u.build().toString();
4✔
106
        } catch (URISyntaxException ex) {
1✔
107
            ex.printStackTrace();
2✔
108
            return "/";
2✔
109
        }
110
    }
111

112
    /**
113
     * Generates a short name for a public key or public key hash.
114
     *
115
     * @param pubkeyOrPubkeyhash the public key (64 characters) or public key hash (40 characters)
116
     * @return a short representation of the public key or public key hash
117
     */
118
    public static String getShortPubkeyName(String pubkeyOrPubkeyhash) {
119
        if (pubkeyOrPubkeyhash.length() == 64) {
4!
120
            return pubkeyOrPubkeyhash.replaceFirst("^(.{8}).*$", "$1");
×
121
        } else {
122
            return pubkeyOrPubkeyhash.replaceFirst("^(.).{39}(.{5}).*$", "$1..$2..");
5✔
123
        }
124
    }
125

126
    public static String getShortPubkeyhashLabel(String pubkeyOrPubkeyhash, IRI user) {
127
        String s = getShortPubkeyName(pubkeyOrPubkeyhash);
×
128
        NanodashSession session = NanodashSession.get();
×
129
        List<String> l = new ArrayList<>();
×
130
        if (pubkeyOrPubkeyhash.equals(session.getPubkeyString()) || pubkeyOrPubkeyhash.equals(session.getPubkeyhash()))
×
131
            l.add("local");
×
132
        // TODO: Make this more efficient:
133
        String hashed = Utils.createSha256HexHash(pubkeyOrPubkeyhash);
×
134
        if (User.getPubkeyhashes(user, true).contains(pubkeyOrPubkeyhash) || User.getPubkeyhashes(user, true).contains(hashed))
×
135
            l.add("approved");
×
136
        if (!l.isEmpty()) s += " (" + String.join("/", l) + ")";
×
137
        return s;
×
138
    }
139

140
    /**
141
     * Retrieves the name of the public key location based on the public key.
142
     *
143
     * @param pubkeyhash the public key string
144
     * @return the name of the public key location
145
     */
146
    public static String getPubkeyLocationName(String pubkeyhash) {
147
        return getPubkeyLocationName(pubkeyhash, getShortPubkeyName(pubkeyhash));
×
148
    }
149

150
    /**
151
     * Retrieves the name of the public key location, or returns a fallback name if not found.
152
     * If the key location is localhost, it returns "localhost".
153
     *
154
     * @param pubkeyhash the public key string
155
     * @param fallback   the fallback name to return if the key location is not found
156
     * @return the name of the public key location or the fallback name
157
     */
158
    public static String getPubkeyLocationName(String pubkeyhash, String fallback) {
159
        IRI keyLocation = User.getUserData().getKeyLocationForPubkeyhash(pubkeyhash);
×
160
        if (keyLocation == null) return fallback;
×
161
        if (keyLocation.stringValue().equals("http://localhost:37373/")) return "localhost";
×
162
        return keyLocation.stringValue().replaceFirst("https?://(nanobench\\.)?(nanodash\\.)?(.*[^/])/?$", "$3");
×
163
    }
164

165
    /**
166
     * Generates a short label for a public key location, including its status (local or approved).
167
     *
168
     * @param pubkeyhash the public key string
169
     * @param user       the IRI of the user associated with the public key
170
     * @return a short label indicating the public key location and its status
171
     */
172
    public static String getShortPubkeyLocationLabel(String pubkeyhash, IRI user) {
173
        String s = getPubkeyLocationName(pubkeyhash);
×
174
        NanodashSession session = NanodashSession.get();
×
175
        List<String> l = new ArrayList<>();
×
176
        if (pubkeyhash.equals(session.getPubkeyhash())) l.add("local");
×
177
        // TODO: Make this more efficient:
178
        if (User.getPubkeyhashes(user, true).contains(pubkeyhash)) l.add("approved");
×
179
        if (!l.isEmpty()) s += " (" + String.join("/", l) + ")";
×
180
        return s;
×
181
    }
182

183
    /**
184
     * Checks if a given public key has a Nanodash location.
185
     * A Nanodash location is identified by specific keywords in the key location.
186
     *
187
     * @param pubkeyhash the public key to check
188
     * @return true if the public key has a Nanodash location, false otherwise
189
     */
190
    public static boolean hasNanodashLocation(String pubkeyhash) {
191
        IRI keyLocation = User.getUserData().getKeyLocationForPubkeyhash(pubkeyhash);
×
192
        if (keyLocation == null) return true; // potentially a Nanodash location
×
193
        if (keyLocation.stringValue().contains("nanodash")) return true;
×
194
        if (keyLocation.stringValue().contains("nanobench")) return true;
×
195
        if (keyLocation.stringValue().contains(":37373")) return true;
×
196
        return false;
×
197
    }
198

199
    /**
200
     * Retrieves the short ORCID ID from an IRI object.
201
     *
202
     * @param orcidIri the IRI object representing the ORCID ID
203
     * @return the short ORCID ID as a string
204
     */
205
    public static String getShortOrcidId(IRI orcidIri) {
206
        return orcidIri.stringValue().replaceFirst("^https://orcid.org/", "");
6✔
207
    }
208

209
    /**
210
     * Retrieves the URI postfix from a given URI object.
211
     *
212
     * @param uri the URI object from which to extract the postfix
213
     * @return the URI postfix as a string
214
     */
215
    public static String getUriPostfix(Object uri) {
216
        String s = uri.toString();
3✔
217
        if (s.contains("#")) return s.replaceFirst("^.*#(.*)$", "$1");
4!
218
        return s.replaceFirst("^.*/(.*)$", "$1");
5✔
219
    }
220

221
    /**
222
     * Retrieves the URI prefix from a given URI object.
223
     *
224
     * @param uri the URI object from which to extract the prefix
225
     * @return the URI prefix as a string
226
     */
227
    public static String getUriPrefix(Object uri) {
228
        String s = uri.toString();
3✔
229
        if (s.contains("#")) return s.replaceFirst("^(.*#).*$", "$1");
4!
230
        return s.replaceFirst("^(.*/).*$", "$1");
5✔
231
    }
232

233
    /**
234
     * Checks if a given string is a valid URI postfix.
235
     * A valid URI postfix does not contain a colon (":").
236
     *
237
     * @param s the string to check
238
     * @return true if the string is a valid URI postfix, false otherwise
239
     */
240
    public static boolean isUriPostfix(String s) {
241
        return !s.contains(":");
8✔
242
    }
243

244
    /**
245
     * Retrieves the location of a given IntroNanopub.
246
     *
247
     * @param inp the IntroNanopub from which to extract the location
248
     * @return the IRI location of the nanopublication, or null if not found
249
     */
250
    public static IRI getLocation(IntroNanopub inp) {
251
        NanopubSignatureElement el = getNanopubSignatureElement(inp);
×
252
        for (KeyDeclaration kd : inp.getKeyDeclarations()) {
×
253
            if (el.getPublicKeyString().equals(kd.getPublicKeyString())) {
×
254
                return kd.getKeyLocation();
×
255
            }
256
        }
×
257
        return null;
×
258
    }
259

260
    /**
261
     * Retrieves the NanopubSignatureElement from a given IntroNanopub.
262
     *
263
     * @param inp the IntroNanopub from which to extract the signature element
264
     * @return the NanopubSignatureElement associated with the nanopublication
265
     */
266
    public static NanopubSignatureElement getNanopubSignatureElement(IntroNanopub inp) {
267
        try {
268
            return SignatureUtils.getSignatureElement(inp.getNanopub());
×
269
        } catch (MalformedCryptoElementException ex) {
×
270
            throw new RuntimeException(ex);
×
271
        }
272
    }
273

274
    /**
275
     * Retrieves a Nanopub object from a given URI if it is a potential Trusty URI.
276
     *
277
     * @param uri the URI to check and retrieve the Nanopub from
278
     * @return the Nanopub object if found, or null if not a known nanopublication
279
     */
280
    public static Nanopub getAsNanopub(String uri) {
281
        if (TrustyUriUtils.isPotentialTrustyUri(uri)) {
×
282
            try {
283
                return Utils.getNanopub(uri);
×
284
            } catch (Exception ex) {
×
285
                // wasn't a known nanopublication
286
            }
287
        }
288
        return null;
×
289
    }
290

291
    private static PolicyFactory htmlSanitizePolicy = new HtmlPolicyBuilder()
3✔
292
            .allowCommonBlockElements()
1✔
293
            .allowCommonInlineFormattingElements()
15✔
294
            .allowUrlProtocols("https", "http", "mailto")
7✔
295
            .allowElements("a")
7✔
296
            .allowAttributes("href").onElements("a")
14✔
297
            .allowElements("img")
7✔
298
            .allowAttributes("src").onElements("img")
8✔
299
            .requireRelNofollowOnLinks()
1✔
300
            .toFactory();
2✔
301

302
    /**
303
     * Sanitizes raw HTML input to ensure safe rendering.
304
     *
305
     * @param rawHtml the raw HTML input to sanitize
306
     * @return sanitized HTML string
307
     */
308
    public static String sanitizeHtml(String rawHtml) {
309
        return htmlSanitizePolicy.sanitize(rawHtml);
4✔
310
    }
311

312
    /**
313
     * Converts PageParameters to a URL-encoded string representation.
314
     *
315
     * @param params the PageParameters to convert
316
     * @return a string representation of the parameters in URL-encoded format
317
     */
318
    public static String getPageParametersAsString(PageParameters params) {
319
        String s = "";
2✔
320
        for (String n : params.getNamedKeys()) {
11✔
321
            if (!s.isEmpty()) s += "&";
6✔
322
            s += n + "=" + URLEncoder.encode(params.get(n).toString(), Charsets.UTF_8);
10✔
323
        }
1✔
324
        return s;
2✔
325
    }
326

327
    /**
328
     * Sets a minimal escape markup function for a Select2Choice component.
329
     * This function replaces certain characters and formats the display of choices.
330
     *
331
     * @param selectItem the Select2Choice component to set the escape markup for
332
     */
333
    public static void setSelect2ChoiceMinimalEscapeMarkup(Select2Choice<?> selectItem) {
334
        selectItem.getSettings().setEscapeMarkup("function(markup) {" +
×
335
                                                 "return markup" +
336
                                                 ".replaceAll('<','&lt;').replaceAll('>', '&gt;')" +
337
                                                 ".replace(/^(.*?) - /, '<span class=\"term\">$1</span><br>')" +
338
                                                 ".replace(/\\((https?:[\\S]+)\\)$/, '<br><code>$1</code>')" +
339
                                                 ".replace(/^([^<].*)$/, '<span class=\"term\">$1</span>')" +
340
                                                 ";}"
341
        );
342
    }
×
343

344
    /**
345
     * Checks if a nanopublication is of a specific class.
346
     *
347
     * @param np       the nanopublication to check
348
     * @param classIri the IRI of the class to check against
349
     * @return true if the nanopublication is of the specified class, false otherwise
350
     */
351
    public static boolean isNanopubOfClass(Nanopub np, IRI classIri) {
352
        return NanopubUtils.getTypes(np).contains(classIri);
5✔
353
    }
354

355
    /**
356
     * Checks if a nanopublication uses a specific predicate in its assertion.
357
     *
358
     * @param np           the nanopublication to check
359
     * @param predicateIri the IRI of the predicate to look for
360
     * @return true if the predicate is used in the assertion, false otherwise
361
     */
362
    public static boolean usesPredicateInAssertion(Nanopub np, IRI predicateIri) {
363
        for (Statement st : np.getAssertion()) {
11✔
364
            if (predicateIri.equals(st.getPredicate())) {
5✔
365
                return true;
2✔
366
            }
367
        }
1✔
368
        return false;
2✔
369
    }
370

371
    /**
372
     * Retrieves a map of FOAF names from the nanopublication's pubinfo.
373
     *
374
     * @param np the nanopublication from which to extract FOAF names
375
     * @return a map where keys are subjects and values are FOAF names
376
     */
377
    public static Map<String, String> getFoafNameMap(Nanopub np) {
378
        Map<String, String> foafNameMap = new HashMap<>();
4✔
379
        for (Statement st : np.getPubinfo()) {
11✔
380
            if (st.getPredicate().equals(FOAF.NAME) && st.getObject() instanceof Literal objL) {
14✔
381
                foafNameMap.put(st.getSubject().stringValue(), objL.stringValue());
8✔
382
            }
383
        }
1✔
384
        return foafNameMap;
2✔
385
    }
386

387
    /**
388
     * Creates an SHA-256 hash of the string representation of an object and returns it as a hexadecimal string.
389
     *
390
     * @param obj the object to hash
391
     * @return the SHA-256 hash of the object's string representation in hexadecimal format
392
     */
393
    public static String createSha256HexHash(Object obj) {
394
        return Hashing.sha256().hashString(obj.toString(), StandardCharsets.UTF_8).toString();
7✔
395
    }
396

397
    /**
398
     * Gets the types of a nanopublication.
399
     *
400
     * @param np the nanopublication from which to extract types
401
     * @return a list of IRI types associated with the nanopublication
402
     */
403
    public static List<IRI> getTypes(Nanopub np) {
404
        List<IRI> l = new ArrayList<IRI>();
4✔
405
        for (IRI t : NanopubUtils.getTypes(np)) {
11✔
406
            if (t.stringValue().equals("https://w3id.org/fair/fip/terms/Available-FAIR-Enabling-Resource")) continue;
6✔
407
            if (t.stringValue().equals("https://w3id.org/fair/fip/terms/FAIR-Enabling-Resource-to-be-Developed"))
5✔
408
                continue;
1✔
409
            if (t.stringValue().equals("https://w3id.org/fair/fip/terms/Available-FAIR-Supporting-Resource")) continue;
5!
410
            if (t.stringValue().equals("https://w3id.org/fair/fip/terms/FAIR-Supporting-Resource-to-be-Developed"))
5!
411
                continue;
×
412
            l.add(t);
4✔
413
        }
1✔
414
        return l;
2✔
415
    }
416

417
    /**
418
     * Gets a label for a type IRI.
419
     *
420
     * @param typeIri the IRI of the type
421
     * @return a label for the type, potentially truncated
422
     */
423
    public static String getTypeLabel(IRI typeIri) {
424
        String l = typeIri.stringValue();
3✔
425
        if (l.equals("https://w3id.org/fair/fip/terms/FAIR-Enabling-Resource")) return "FER";
6✔
426
        if (l.equals("https://w3id.org/fair/fip/terms/FAIR-Supporting-Resource")) return "FSR";
6✔
427
        if (l.equals("https://w3id.org/fair/fip/terms/FAIR-Implementation-Profile")) return "FIP";
6✔
428
        if (l.equals("http://purl.org/nanopub/x/declaredBy")) return "user intro";
6✔
429
        l = l.replaceFirst("^.*[/#]([^/#]+)[/#]?$", "$1");
5✔
430
        l = l.replaceFirst("^(.+)Nanopub$", "$1");
5✔
431
        if (l.length() > 25) l = l.substring(0, 20) + "...";
10✔
432
        return l;
2✔
433
    }
434

435
    /**
436
     * Gets a label for a URI.
437
     *
438
     * @param uri the URI to get the label from
439
     * @return a label for the URI, potentially truncated
440
     */
441
    public static String getUriLabel(String uri) {
442
        if (uri == null) return "";
4✔
443
        String uriLabel = uri;
2✔
444
        if (uriLabel.matches(".*[^A-Za-z0-9-_]RA[A-Za-z0-9-_]{43}([^A-Za-z0-9-_].*)?")) {
4✔
445
            String newUriLabel = uriLabel.replaceFirst("(.*[^A-Za-z0-9-_]RA[A-Za-z0-9-_]{8})[A-Za-z0-9-_]{35}([^A-Za-z0-9-_].*)?", "$1...$2");
5✔
446
            if (newUriLabel.length() <= 70) return newUriLabel;
6!
447
        }
448
        if (uriLabel.length() > 70) return uri.substring(0, 30) + "..." + uri.substring(uri.length() - 30);
16✔
449
        return uriLabel;
2✔
450
    }
451

452
    /**
453
     * Gets an ExternalLink with a URI label.
454
     *
455
     * @param markupId the markup ID for the link
456
     * @param uri      the URI to link to
457
     * @return an ExternalLink with the URI label
458
     */
459
    public static ExternalLink getUriLink(String markupId, String uri) {
460
        return new ExternalLink(markupId, (uri.startsWith("local:") ? "" : uri), getUriLabel(uri));
12!
461
    }
462

463
    /**
464
     * Gets an ExternalLink with a model for the URI label.
465
     *
466
     * @param markupId the markup ID for the link
467
     * @param model    the model containing the URI
468
     * @return an ExternalLink with the URI label
469
     */
470
    public static ExternalLink getUriLink(String markupId, IModel<String> model) {
471
        return new ExternalLink(markupId, model, new UriLabelModel(model));
×
472
    }
473

474
    private static class UriLabelModel implements IModel<String> {
475

476
        private static final long serialVersionUID = 1L;
477

478
        private IModel<String> uriModel;
479

480
        public UriLabelModel(IModel<String> uriModel) {
×
481
            this.uriModel = uriModel;
×
482
        }
×
483

484
        @Override
485
        public String getObject() {
486
            return getUriLabel(uriModel.getObject());
×
487
        }
488

489
    }
490

491
    /**
492
     * Creates a sublist from a list based on the specified indices.
493
     *
494
     * @param list      the list from which to create the sublist
495
     * @param fromIndex the starting index (inclusive) for the sublist
496
     * @param toIndex   the ending index (exclusive) for the sublist
497
     * @param <E>       the type of elements in the list
498
     * @return an ArrayList containing the elements from the specified range
499
     */
500
    public static <E> ArrayList<E> subList(List<E> list, long fromIndex, long toIndex) {
501
        // So the resulting list is serializable:
502
        return new ArrayList<E>(list.subList((int) fromIndex, (int) toIndex));
×
503
    }
504

505
    /**
506
     * Creates a sublist from an array based on the specified indices.
507
     *
508
     * @param array     the array from which to create the sublist
509
     * @param fromIndex the starting index (inclusive) for the sublist
510
     * @param toIndex   the ending index (exclusive) for the sublist
511
     * @param <E>       the type of elements in the array
512
     * @return an ArrayList containing the elements from the specified range
513
     */
514
    public static <E> ArrayList<E> subList(E[] array, long fromIndex, long toIndex) {
515
        return subList(Arrays.asList(array), fromIndex, toIndex);
×
516
    }
517

518
    /**
519
     * Comparator for sorting ApiResponseEntry objects based on a specified field.
520
     */
521
    // TODO Move this to ApiResponseEntry class?
522
    public static class ApiResponseEntrySorter implements Comparator<ApiResponseEntry>, Serializable {
523

524
        private static final long serialVersionUID = 1L;
525

526
        private String field;
527
        private boolean descending;
528

529
        /**
530
         * Constructor for ApiResponseEntrySorter.
531
         *
532
         * @param field      the field to sort by
533
         * @param descending if true, sorts in descending order; if false, sorts in ascending order
534
         */
535
        public ApiResponseEntrySorter(String field, boolean descending) {
×
536
            this.field = field;
×
537
            this.descending = descending;
×
538
        }
×
539

540
        /**
541
         * Compares two ApiResponseEntry objects based on the specified field.
542
         *
543
         * @param o1 the first object to be compared.
544
         * @param o2 the second object to be compared.
545
         * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
546
         */
547
        @Override
548
        public int compare(ApiResponseEntry o1, ApiResponseEntry o2) {
549
            if (descending) {
×
550
                return o2.get(field).compareTo(o1.get(field));
×
551
            } else {
552
                return o1.get(field).compareTo(o2.get(field));
×
553
            }
554
        }
555

556
    }
557

558
    /**
559
     * MIME type for TriG RDF format.
560
     */
561
    public static final String TYPE_TRIG = "application/trig";
562

563
    /**
564
     * MIME type for Jelly RDF format.
565
     */
566
    public static final String TYPE_JELLY = "application/x-jelly-rdf";
567

568
    /**
569
     * MIME type for JSON-LD format.
570
     */
571
    public static final String TYPE_JSONLD = "application/ld+json";
572

573
    /**
574
     * MIME type for N-Quads format.
575
     */
576
    public static final String TYPE_NQUADS = "application/n-quads";
577

578
    /**
579
     * MIME type for Trix format.
580
     */
581
    public static final String TYPE_TRIX = "application/trix";
582

583
    /**
584
     * MIME type for HTML format.
585
     */
586
    public static final String TYPE_HTML = "text/html";
587

588
    public static final String SUPPORTED_TYPES =
589
            TYPE_TRIG + "," +
590
            TYPE_JELLY + "," +
591
            TYPE_JSONLD + "," +
592
            TYPE_NQUADS + "," +
593
            TYPE_TRIX + "," +
594
            TYPE_HTML;
595

596
    /**
597
     * List of supported MIME types for nanopublications.
598
     */
599
    public static final List<String> SUPPORTED_TYPES_LIST = Arrays.asList(StringUtils.split(SUPPORTED_TYPES, ','));
6✔
600

601
    // TODO Move these to nanopub-java library:
602

603
    /**
604
     * Retrieves a set of introduced IRI IDs from the nanopublication.
605
     *
606
     * @param np the nanopublication from which to extract introduced IRI IDs
607
     * @return a set of introduced IRI IDs
608
     */
609
    public static Set<String> getIntroducedIriIds(Nanopub np) {
610
        Set<String> introducedIriIds = new HashSet<>();
4✔
611
        for (Statement st : np.getPubinfo()) {
11✔
612
            if (!st.getSubject().equals(np.getUri())) continue;
7✔
613
            if (!st.getPredicate().equals(NanopubUtils.INTRODUCES)) continue;
6✔
614
            if (st.getObject() instanceof IRI obj) introducedIriIds.add(obj.stringValue());
14✔
615
        }
1✔
616
        return introducedIriIds;
2✔
617
    }
618

619
    /**
620
     * Retrieves a set of embedded IRI IDs from the nanopublication.
621
     *
622
     * @param np the nanopublication from which to extract embedded IRI IDs
623
     * @return a set of embedded IRI IDs
624
     */
625
    public static Set<String> getEmbeddedIriIds(Nanopub np) {
626
        Set<String> embeddedIriIds = new HashSet<>();
×
627
        for (Statement st : np.getPubinfo()) {
×
628
            if (!st.getSubject().equals(np.getUri())) continue;
×
629
            if (!st.getPredicate().equals(NanopubUtils.EMBEDS)) continue;
×
630
            if (st.getObject() instanceof IRI obj) embeddedIriIds.add(obj.stringValue());
×
631
        }
×
632
        return embeddedIriIds;
×
633
    }
634

635
    /**
636
     * Returns the URL of the default Nanopub Registry as configured by the given instance.
637
     *
638
     * @return Nanopub Registry URL
639
     */
640
    public static String getMainRegistryUrl() {
641
        try {
642
            return EnvironmentUtils.getProcEnvironment().getOrDefault("NANODASH_MAIN_REGISTRY", "https://registry.knowledgepixels.com/");
6✔
643
        } catch (IOException ex) {
×
644
            ex.printStackTrace();
×
645
            return "https://registry.knowledgepixels.com/";
×
646
        }
647
    }
648

649
    /**
650
     * Checks whether string is valid literal serialization.
651
     *
652
     * @param literalString the literal string
653
     * @return true if valid
654
     */
655
    public static boolean isValidLiteralSerialization(String literalString) {
656
        return literalString.matches("\"([^\\\\\\\"]|\\\\\\\\|\\\\\")*\"");
×
657
    }
658

659
    /**
660
     * Returns a serialized version of the literal.
661
     *
662
     * @param literal the literal
663
     * @return the String serialization of the literal
664
     */
665
    public static String getSerializedLiteral(Literal literal) {
666
        return "\"" + getEscapedLiteralString(literal.stringValue()) + "\"";
×
667
    }
668

669
    /**
670
     * Parses a serialized literal into a Literal object.
671
     *
672
     * @param serializedLiteral The serialized String of the literal
673
     * @return The parse Literal object
674
     */
675
    public static Literal getParsedLiteral(String serializedLiteral) {
676
        return vf.createLiteral(getUnescapedLiteralString(serializedLiteral.substring(1, serializedLiteral.length() - 1)));
×
677
    }
678

679
    /**
680
     * Escapes quotes (") and slashes (/) of a literal string.
681
     *
682
     * @param unescapedString un-escaped string
683
     * @return escaped string
684
     */
685
    public static String getEscapedLiteralString(String unescapedString) {
686
        return unescapedString.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\"");
×
687
    }
688

689
    /**
690
     * Un-escapes quotes (") and slashes (/) of a literal string.
691
     *
692
     * @param unescapedString escaped string
693
     * @return un-escaped string
694
     */
695
    public static String getUnescapedLiteralString(String escapedString) {
696
        return escapedString.replaceAll("\\\\(\\\\|\\\")", "$1");
×
697
    }
698

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