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

knowledgepixels / nanodash / 18155160356

01 Oct 2025 07:42AM UTC coverage: 13.788% (-0.03%) from 13.817%
18155160356

push

github

ashleycaselli
docs: add missing or update Javadoc annotations

445 of 4084 branches covered (10.9%)

Branch coverage included in aggregate %.

1155 of 7520 relevant lines covered (15.36%)

0.69 hits per line

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

80.33
src/main/java/com/knowledgepixels/nanodash/GrlcQuery.java
1
package com.knowledgepixels.nanodash;
2

3
import com.knowledgepixels.nanodash.component.QueryParamField;
4
import net.trustyuri.TrustyUriUtils;
5
import org.eclipse.rdf4j.model.IRI;
6
import org.eclipse.rdf4j.model.Literal;
7
import org.eclipse.rdf4j.model.Statement;
8
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
9
import org.eclipse.rdf4j.model.vocabulary.RDF;
10
import org.eclipse.rdf4j.model.vocabulary.RDFS;
11
import org.eclipse.rdf4j.query.algebra.Var;
12
import org.eclipse.rdf4j.query.algebra.helpers.AbstractSimpleQueryModelVisitor;
13
import org.eclipse.rdf4j.query.parser.ParsedQuery;
14
import org.eclipse.rdf4j.query.parser.sparql.SPARQLParser;
15
import org.nanopub.Nanopub;
16
import org.nanopub.extra.services.QueryRef;
17
import org.slf4j.Logger;
18
import org.slf4j.LoggerFactory;
19

20
import java.io.Serializable;
21
import java.util.*;
22

23
/**
24
 * Represents a GRLC query extracted from a nanopublication.
25
 * This class parses the query details, including SPARQL, endpoint, label, description, and placeholders.
26
 */
27
public class GrlcQuery implements Serializable {
28

29
    private static final Logger logger = LoggerFactory.getLogger(GrlcQuery.class);
3✔
30

31
    private static Map<String, GrlcQuery> instanceMap = new HashMap<>();
4✔
32

33
    /**
34
     * Returns a singleton instance of GrlcQuery for the given QueryRef.
35
     *
36
     * @param ref the QueryRef object containing the query name
37
     * @return a GrlcQuery instance
38
     */
39
    public static GrlcQuery get(QueryRef ref) {
40
        return get(ref.getName());
×
41
    }
42

43
    /**
44
     * Returns a singleton instance of GrlcQuery for the given query ID.
45
     *
46
     * @param id the unique identifier or URI of the query
47
     * @return a GrlcQuery instance
48
     */
49
    public static GrlcQuery get(String id) {
50
        if (!instanceMap.containsKey(id)) {
4!
51
            try {
52
                GrlcQuery q = new GrlcQuery(id);
5✔
53
                id = q.getQueryId();
3✔
54
                if (instanceMap.containsKey(id)) return instanceMap.get(id);
9✔
55
                instanceMap.put(id, q);
5✔
56
            } catch (Exception ex) {
1✔
57
                logger.error("Could not load query: {}", id, ex);
5✔
58
            }
1✔
59
        }
60
        return instanceMap.get(id);
5✔
61
    }
62

63
    /**
64
     * The IRI for the GRLC query class and properties.
65
     */
66
    public final static IRI GRLC_QUERY_CLASS = Utils.vf.createIRI("https://w3id.org/kpxl/grlc/grlc-query");
4✔
67

68
    /**
69
     * The IRI for the SPARQL property and endpoint property in GRLC queries.
70
     */
71
    public final static IRI GRLC_HAS_SPARQL = Utils.vf.createIRI("https://w3id.org/kpxl/grlc/sparql");
4✔
72

73
    /**
74
     * The IRI for the endpoint property in GRLC queries.
75
     */
76
    public final static IRI GRLC_HAS_ENDPOINT = Utils.vf.createIRI("https://w3id.org/kpxl/grlc/endpoint");
5✔
77

78
    private final String queryId;
79
    private final String artifactCode;
80
    private final String querySuffix;
81
    private final Nanopub nanopub;
82
    private IRI queryUri;
83
    private String sparql;
84
    private IRI endpoint;
85
    private String label;
86
    private String description;
87
    private final List<String> placeholdersList;
88

89
    /**
90
     * Constructs a GrlcQuery object by parsing the provided query ID or URI.
91
     *
92
     * @param id The query ID or URI.
93
     * @throws IllegalArgumentException If the ID is null, invalid, or the nanopublication defines multiple queries.
94
     */
95
    private GrlcQuery(String id) {
2✔
96
        if (id == null) {
2✔
97
            throw new IllegalArgumentException("Null value for query ID");
5✔
98
        }
99
        if (TrustyUriUtils.isPotentialTrustyUri(id)) {
3!
100
            artifactCode = TrustyUriUtils.getArtifactCode(id);
4✔
101
            nanopub = Utils.getNanopub(artifactCode);
5✔
102
            for (Statement st : nanopub.getAssertion()) {
12✔
103
                if (st.getPredicate().equals(RDF.TYPE) && st.getObject().equals(GRLC_QUERY_CLASS)) {
10!
104
                    if (queryUri != null) {
3✔
105
                        throw new IllegalArgumentException("Nanopublication defines more than one query: " + id);
6✔
106
                    }
107
                    queryUri = (IRI) st.getSubject();
5✔
108
                }
109
            }
1✔
110
            if (queryUri == null) {
3✔
111
                throw new IllegalArgumentException("No query found in nanopublication: " + id);
6✔
112
            }
113
            queryId = queryUri.stringValue().replaceFirst("^https?://.*[^A-Za-z0-9-_](RA[A-Za-z0-9-_]{43}[/#][^/#]+)$", "$1").replace("#", "/");
12✔
114
        } else {
115
            if (id.matches("https?://.*[^A-Za-z0-9-_]RA[A-Za-z0-9-_]{43}[/#][^/#]+")) {
×
116
                queryId = id.replaceFirst("^https?://.*[^A-Za-z0-9-_](RA[A-Za-z0-9-_]{43}[/#][^/#]+)$", "$1").replace("#", "/");
×
117
            } else if (id.matches("RA[A-Za-z0-9-_]{43}[/#][^/#]+")) {
×
118
                queryId = id;
×
119
            } else {
120
                throw new IllegalArgumentException("Not a valid query ID or URI: " + id);
×
121
            }
122
            artifactCode = queryId.replaceFirst("[/#].*$", "");
×
123
            nanopub = Utils.getNanopub(artifactCode);
×
124
        }
125
        querySuffix = queryId.replaceFirst("^.*[/#]", "");
7✔
126
        for (Statement st : nanopub.getAssertion()) {
12✔
127
            if (!st.getSubject().stringValue().replace("#", "/").endsWith(queryId)) continue;
10!
128
            queryUri = (IRI) st.getSubject();
5✔
129
            if (st.getPredicate().equals(GRLC_HAS_SPARQL) && st.getObject() instanceof Literal objLiteral) {
14!
130
                sparql = objLiteral.stringValue();
5✔
131
            } else if (st.getPredicate().equals(GRLC_HAS_ENDPOINT) && st.getObject() instanceof IRI objIri) {
14!
132
                endpoint = objIri;
4✔
133
            } else if (st.getPredicate().equals(RDFS.LABEL)) {
5✔
134
                label = st.getObject().stringValue();
6✔
135
            } else if (st.getPredicate().equals(DCTERMS.DESCRIPTION)) {
5✔
136
                description = st.getObject().stringValue();
5✔
137
            }
138
        }
1✔
139

140
        final Set<String> placeholders = new HashSet<>();
4✔
141
        ParsedQuery query = new SPARQLParser().parseQuery(sparql, null);
8✔
142
        query.getTupleExpr().visitChildren(new AbstractSimpleQueryModelVisitor<>() {
14✔
143

144
            @Override
145
            public void meet(Var node) throws RuntimeException {
146
                super.meet(node);
3✔
147
                if (!node.isConstant() && !node.isAnonymous() && node.getName().startsWith("_")) {
11!
148
                    placeholders.add(node.getName());
×
149
                }
150
            }
1✔
151

152
        });
153
        List<String> placeholdersListPre = new ArrayList<>(placeholders);
5✔
154
        Collections.sort(placeholdersListPre);
2✔
155
        placeholdersList = Collections.unmodifiableList(placeholdersListPre);
4✔
156
    }
1✔
157

158
    /**
159
     * Returns the unique query ID.
160
     *
161
     * @return The query ID.
162
     */
163
    public String getQueryId() {
164
        return queryId;
3✔
165
    }
166

167
    /**
168
     * Returns the artifact code extracted from the nanopublication.
169
     *
170
     * @return The artifact code.
171
     */
172
    public String getArtifactCode() {
173
        return artifactCode;
3✔
174
    }
175

176
    /**
177
     * Returns the suffix of the query.
178
     *
179
     * @return The query suffix.
180
     */
181
    public String getQuerySuffix() {
182
        return querySuffix;
3✔
183
    }
184

185
    /**
186
     * Returns the nanopublication containing the query.
187
     *
188
     * @return The nanopublication.
189
     */
190
    public Nanopub getNanopub() {
191
        return nanopub;
3✔
192
    }
193

194
    /**
195
     * Returns the URI of the query.
196
     *
197
     * @return The query URI.
198
     */
199
    public IRI getQueryUri() {
200
        return queryUri;
3✔
201
    }
202

203
    /**
204
     * Returns the SPARQL query string.
205
     *
206
     * @return The SPARQL query.
207
     */
208
    public String getSparql() {
209
        return sparql;
3✔
210
    }
211

212
    /**
213
     * Returns the endpoint URI for the query.
214
     *
215
     * @return The endpoint URI.
216
     */
217
    public IRI getEndpoint() {
218
        return endpoint;
3✔
219
    }
220

221
    /**
222
     * Returns the label of the query.
223
     *
224
     * @return The query label.
225
     */
226
    public String getLabel() {
227
        return label;
3✔
228
    }
229

230
    /**
231
     * Returns the description of the query.
232
     *
233
     * @return The query description.
234
     */
235
    public String getDescription() {
236
        return description;
3✔
237
    }
238

239
    /**
240
     * Returns a list of placeholders in the query.
241
     *
242
     * @return The list of placeholders.
243
     */
244
    public List<String> getPlaceholdersList() {
245
        return placeholdersList;
3✔
246
    }
247

248
    /**
249
     * Creates a list of query parameter fields for the placeholders in the query.
250
     *
251
     * @param markupId The markup ID for the fields.
252
     * @return A list of query parameter fields.
253
     */
254
    public List<QueryParamField> createParamFields(String markupId) {
255
        List<QueryParamField> l = new ArrayList<>();
4✔
256
        for (String s : placeholdersList) {
7!
257
            l.add(new QueryParamField(markupId, s));
×
258
        }
×
259
        return l;
2✔
260
    }
261

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