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

knowledgepixels / nanopub-registry / 21143551066

19 Jan 2026 03:44PM UTC coverage: 18.779% (+1.2%) from 17.551%
21143551066

push

github

ashleycaselli
docs(Utils): add missing Javadoc annotations

96 of 586 branches covered (16.38%)

Branch coverage included in aggregate %.

350 of 1789 relevant lines covered (19.56%)

3.59 hits per line

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

88.89
src/main/java/com/knowledgepixels/registry/Utils.java
1
package com.knowledgepixels.registry;
2

3
import com.github.jsonldjava.shaded.com.google.common.base.Charsets;
4
import com.github.jsonldjava.shaded.com.google.common.reflect.TypeToken;
5
import com.google.common.hash.Hashing;
6
import com.google.gson.Gson;
7
import com.google.gson.JsonIOException;
8
import com.google.gson.JsonSyntaxException;
9
import com.mongodb.client.ClientSession;
10
import io.vertx.ext.web.RoutingContext;
11
import net.trustyuri.TrustyUriUtils;
12
import org.apache.commons.lang.StringUtils;
13
import org.commonjava.mimeparse.MIMEParse;
14
import org.eclipse.rdf4j.common.exception.RDF4JException;
15
import org.eclipse.rdf4j.model.IRI;
16
import org.eclipse.rdf4j.model.Resource;
17
import org.eclipse.rdf4j.model.Statement;
18
import org.eclipse.rdf4j.model.util.Values;
19
import org.nanopub.MalformedNanopubException;
20
import org.nanopub.Nanopub;
21
import org.nanopub.NanopubImpl;
22
import org.nanopub.NanopubUtils;
23
import org.nanopub.extra.setting.NanopubSetting;
24
import org.nanopub.vocabulary.NPX;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27

28
import java.io.File;
29
import java.io.IOException;
30
import java.io.InputStreamReader;
31
import java.lang.reflect.Type;
32
import java.net.URI;
33
import java.net.URISyntaxException;
34
import java.net.URLEncoder;
35
import java.nio.charset.StandardCharsets;
36
import java.util.*;
37

38
/**
39
 * Utility class for the Nanopub Registry.
40
 */
41
public class Utils {
42

43
    private static final Logger logger = LoggerFactory.getLogger(Utils.class);
12✔
44

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

48
    public static String getMimeType(RoutingContext context, String supported) {
49
        List<String> supportedList = Arrays.asList(StringUtils.split(supported, ','));
×
50
        String mimeType = supportedList.getFirst();
×
51
        try {
52
            mimeType = MIMEParse.bestMatch(supportedList, context.request().getHeader("Accept"));
×
53
        } catch (Exception ex) {
×
54
            logger.error("Error parsing Accept header.", ex);
×
55
        }
×
56
        return mimeType;
×
57
    }
58

59
    public static String urlEncode(Object o) {
60
        return URLEncoder.encode((o == null ? "" : o.toString()), StandardCharsets.UTF_8);
36✔
61
    }
62

63
    public static String getHash(String s) {
64
        return Hashing.sha256().hashString(s, Charsets.UTF_8).toString();
24✔
65
    }
66

67
    /**
68
     * Get the IDs of nanopublications invalidated by the given nanopublication.
69
     *
70
     * @param np the nanopublication to check
71
     * @return a set of IRI IDs of invalidated nanopublications
72
     */
73
    public static Set<IRI> getInvalidatedNanopubIds(Nanopub np) {
74
        Set<IRI> invalidatedNanopubs = new HashSet<>();
16✔
75
        for (Statement st : NanopubUtils.getStatements(np)) {
44✔
76
            if (!(st.getObject() instanceof IRI)) continue;
20✔
77
            Resource subject = st.getSubject();
12✔
78
            IRI predicate = st.getPredicate();
12✔
79
            if ((predicate.equals(NPX.RETRACTS) || predicate.equals(NPX.INVALIDATES)) || (predicate.equals(NPX.SUPERSEDES) && subject.equals(np.getUri()))) {
48!
80
                if (TrustyUriUtils.isPotentialTrustyUri(st.getObject().stringValue())) {
20!
81
                    invalidatedNanopubs.add((IRI) st.getObject());
24✔
82
                }
83
            }
84
        }
4✔
85
        return invalidatedNanopubs;
8✔
86
    }
87

88
    private static ReadsEnvironment ENV_READER = new ReadsEnvironment(System::getenv);
20✔
89

90
    /**
91
     * Set the environment reader (used for testing purposes).
92
     *
93
     * @param reader the environment reader to set
94
     */
95
    static void setEnvReader(ReadsEnvironment reader) {
96
        ENV_READER = reader;
8✔
97
    }
4✔
98

99
    /**
100
     * Get an environment variable, returning a default value if not set.
101
     *
102
     * @param name         the name of the environment variable
103
     * @param defaultValue the default value to return if the variable is not set
104
     * @return the value of the environment variable, or the default value if not set
105
     */
106
    public static String getEnv(String name, String defaultValue) {
107
        logger.info("Retrieving environment variable: {}", name);
16✔
108
        String value = ENV_READER.getEnv(name);
16✔
109
        if (value == null) {
8✔
110
            value = defaultValue;
8✔
111
            logger.info("The variable: {} is not set. Using default value: {}", name, defaultValue);
20✔
112
        }
113
        return value;
8✔
114
    }
115

116
    /**
117
     * Get the type hash for a given type, recording it in the database if necessary.
118
     *
119
     * @param mongoSession the MongoDB client session
120
     * @param type         the type to get the hash for
121
     * @return the type hash
122
     */
123
    public static String getTypeHash(ClientSession mongoSession, Object type) {
124
        String typeHash = Utils.getHash(type.toString());
16✔
125
        if (type.toString().equals("$")) {
20✔
126
            typeHash = "$";
12✔
127
        } else {
128
            RegistryDB.recordHash(mongoSession, type.toString());
16✔
129
        }
130
        return typeHash;
8✔
131
    }
132

133
    /**
134
     * Get a label for an agent ID, truncating if necessary.
135
     *
136
     * @param agentId the agent ID
137
     * @return the agent label
138
     */
139
    public static String getAgentLabel(String agentId) {
140
        if (agentId == null || agentId.isBlank()) {
20✔
141
            throw new IllegalArgumentException("Agent ID cannot be null or blank");
20✔
142
        }
143
        agentId = agentId.replaceFirst("^https://orcid\\.org/", "orcid:");
20✔
144
        if (agentId.length() > 55) {
16✔
145
            return agentId.substring(0, 50) + "...";
24✔
146
        }
147
        return agentId;
8✔
148
    }
149

150
    /**
151
     * Check if the given status indicates an unloaded entry.
152
     *
153
     * @param status the status to check
154
     * @return true if the status indicates an unloaded entry, false otherwise
155
     */
156
    public static boolean isUnloadedStatus(String status) {
157
        if (status.equals(EntryStatus.seen.getValue())) return true;  // only exists in "accounts_loading"?
28✔
158
        return status.equals(EntryStatus.skipped.getValue());
20✔
159
    }
160

161
    /**
162
     * Check if the given status indicates a core loaded entry.
163
     *
164
     * @param status the status to check
165
     * @return true if the status indicates a core loaded entry, false otherwise
166
     */
167
    public static boolean isCoreLoadedStatus(String status) {
168
        if (status.equals(EntryStatus.visited.getValue())) return true;  // only exists in "accounts_loading"?
28✔
169
        if (status.equals(EntryStatus.expanded.getValue())) return true;  // only exists in "accounts_loading"?
28✔
170
        if (status.equals(EntryStatus.processed.getValue())) return true;  // only exists in "accounts_loading"?
28✔
171
        if (status.equals(EntryStatus.aggregated.getValue())) return true;  // only exists in "accounts_loading"?
28✔
172
        if (status.equals(EntryStatus.approved.getValue())) return true;  // only exists in "accounts_loading"?
28✔
173
        if (status.equals(EntryStatus.contested.getValue())) return true;
28✔
174
        if (status.equals(EntryStatus.toLoad.getValue())) return true;  // only exists in "accounts_loading"?
28✔
175
        return status.equals(EntryStatus.loaded.getValue());
20✔
176
    }
177

178
    /**
179
     * Check if the given status indicates a fully loaded entry.
180
     *
181
     * @param status the status to check
182
     * @return true if the status indicates a fully loaded entry, false otherwise
183
     */
184
    public static boolean isFullyLoadedStatus(String status) {
185
        return status.equals(EntryStatus.loaded.getValue());
20✔
186
    }
187

188
    public static final IRI APPROVES_OF = Values.iri("http://purl.org/nanopub/x/approvesOf");
12✔
189

190
    public static final String TYPE_JSON = "application/json";
191
    public static final String TYPE_TRIG = "application/trig";
192
    public static final String TYPE_JELLY = "application/x-jelly-rdf";
193
    public static final String TYPE_JSONLD = "application/ld+json";
194
    public static final String TYPE_NQUADS = "application/n-quads";
195
    public static final String TYPE_TRIX = "application/trix";
196
    public static final String TYPE_HTML = "text/html";
197

198
    // Content types supported on a ListPage
199
    public static final String SUPPORTED_TYPES_LIST = TYPE_JSON + "," + TYPE_JELLY + "," + TYPE_HTML;
200
    // Content types supported on a NanopubPage
201
    public static final String SUPPORTED_TYPES_NANOPUB = TYPE_TRIG + "," + TYPE_JELLY + "," + TYPE_JSONLD + "," + TYPE_NQUADS + "," + TYPE_TRIX + "," + TYPE_HTML;
202

203
    private static Map<String, String> extensionTypeMap;
204

205
    /**
206
     * Get the type corresponding to a given file extension.
207
     *
208
     * @param extension the file extension
209
     * @return the corresponding MIME type, or null if not found
210
     */
211
    public static String getType(String extension) {
212
        if (extension == null) {
8✔
213
            return null;
8✔
214
        }
215
        if (extensionTypeMap == null) {
8✔
216
            extensionTypeMap = new HashMap<>();
16✔
217
            extensionTypeMap.put("trig", TYPE_TRIG);
20✔
218
            extensionTypeMap.put("jelly", TYPE_JELLY);
20✔
219
            extensionTypeMap.put("jsonld", TYPE_JSONLD);
20✔
220
            extensionTypeMap.put("nq", TYPE_NQUADS);
20✔
221
            extensionTypeMap.put("xml", TYPE_TRIX);
20✔
222
            extensionTypeMap.put("html", TYPE_HTML);
20✔
223
            extensionTypeMap.put("json", TYPE_JSON);
20✔
224
        }
225
        return extensionTypeMap.get(extension);
20✔
226
    }
227

228
    private static List<String> peerUrls;
229

230
    /**
231
     * Get the list of peer registry URLs.
232
     *
233
     * @return the list of peer registry URLs
234
     */
235
    public static List<String> getPeerUrls() {
236
        if (peerUrls == null) {
8✔
237
            peerUrls = new ArrayList<>();
16✔
238
            String envPeerUrls = getEnv("REGISTRY_PEER_URLS", "");
16✔
239
            String thisRegistryUrl = getEnv("REGISTRY_SERVICE_URL", "");
16✔
240
            if (!envPeerUrls.isEmpty()) {
12✔
241
                for (String peerUrl : envPeerUrls.split(";")) {
76✔
242
                    if (thisRegistryUrl.equals(peerUrl)) {
16!
243
                        continue;
×
244
                    }
245
                    peerUrls.add(peerUrl);
16✔
246
                }
247
            } else {
248
                NanopubSetting setting;
249
                try {
250
                    setting = getSetting();
8✔
251
                } catch (MalformedNanopubException | IOException ex) {
4✔
252
                    logger.error("Error loading registry setting: {}", ex.getMessage());
20✔
253
                    throw new RuntimeException(ex);
20✔
254
                }
4✔
255
                for (IRI iri : setting.getBootstrapServices()) {
44✔
256
                    String peerUrl = iri.stringValue();
12✔
257
                    if (thisRegistryUrl.equals(peerUrl)) {
16!
258
                        continue;
×
259
                    }
260
                    peerUrls.add(peerUrl);
16✔
261
                }
4✔
262
            }
263
        }
264
        return peerUrls;
8✔
265
    }
266

267
    private static volatile NanopubSetting settingNp;
268

269
    /**
270
     * Get the nanopublication setting.
271
     *
272
     * @return the nanopublication setting
273
     * @throws RDF4JException            if there is an error retrieving the setting
274
     * @throws MalformedNanopubException if the setting nanopublication is malformed
275
     * @throws IOException               if there is an I/O error
276
     */
277
    public static NanopubSetting getSetting() throws RDF4JException, MalformedNanopubException, IOException {
278
        if (settingNp == null) {
8✔
279
            synchronized (Utils.class) {
16✔
280
                if (settingNp == null) {
8!
281
                    String settingPath = getEnv("REGISTRY_SETTING_FILE", "/data/setting.trig");
16✔
282
                    settingNp = new NanopubSetting(new NanopubImpl(new File(settingPath)));
44✔
283
                }
284
            }
12✔
285
        }
286
        return settingNp;
8✔
287
    }
288

289
    /**
290
     * Get a random peer registry URL.
291
     *
292
     * @return a random peer registry URL
293
     * @throws RDF4JException if there is an error retrieving the peer URLs
294
     */
295
    public static String getRandomPeer() throws RDF4JException {
296
        List<String> peerUrls = getPeerUrls();
8✔
297
        return peerUrls.get(random.nextInt(peerUrls.size()));
32✔
298
    }
299

300
    private static final Random random = new Random();
16✔
301

302
    /**
303
     * Get the random number generator.
304
     *
305
     * @return the random number generator
306
     */
307
    public static Random getRandom() {
308
        return random;
8✔
309
    }
310

311
    private static final Gson g = new Gson();
16✔
312
    private static Type listType = new TypeToken<List<String>>() {
28✔
313
    }.getType();
8✔
314

315
    /**
316
     * Retrieve a list of strings from a JSON URL.
317
     *
318
     * @param url the URL to retrieve the JSON from
319
     * @return the list of strings
320
     * @throws JsonIOException     if there is an error reading the JSON
321
     * @throws JsonSyntaxException if the JSON syntax is invalid
322
     * @throws IOException         if there is an I/O error
323
     * @throws URISyntaxException  if the URL syntax is invalid
324
     */
325
    public static List<String> retrieveListFromJsonUrl(String url) throws JsonIOException, JsonSyntaxException, IOException, URISyntaxException {
326
        return g.fromJson(new InputStreamReader(new URI(url).toURL().openStream()), listType);
×
327
    }
328

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